|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace App\Services\Subtitles; |
| 4 | + |
| 5 | +use App\Models\Metadata; |
| 6 | +use App\Models\Subtitle; |
| 7 | +use Illuminate\Support\Facades\Log; |
| 8 | +use Illuminate\Support\Facades\Storage; |
| 9 | +use Symfony\Component\Process\Process; |
| 10 | + |
| 11 | +class SubtitleExtractor { |
| 12 | + public function extractStream(Metadata $metadata, Subtitle $subtitle) { |
| 13 | + try { |
| 14 | + $mediaPath = $metadata->video->path; |
| 15 | + $ext = $this->getExtentionFromCodec($subtitle['codec']); |
| 16 | + |
| 17 | + $outputPath = $this->getOutputDir($subtitle, $ext); |
| 18 | + |
| 19 | + $command = [ |
| 20 | + 'ffmpeg', |
| 21 | + '-y', |
| 22 | + '-i', |
| 23 | + Storage::disk('public')->path($mediaPath), // Media is on public disk for now |
| 24 | + '-map', |
| 25 | + "0:$subtitle->track_id", |
| 26 | + Storage::disk('local')->path($outputPath), |
| 27 | + ]; |
| 28 | + |
| 29 | + $process = new Process($command); |
| 30 | + $process->run(); |
| 31 | + |
| 32 | + if (! $process->isSuccessful()) { |
| 33 | + throw new \Exception('Subtitles Failed: "' . implode(' ', $command) . '"'); |
| 34 | + } |
| 35 | + |
| 36 | + $subtitle->update([ |
| 37 | + 'path' => $outputPath, |
| 38 | + 'format' => $ext, |
| 39 | + ]); |
| 40 | + |
| 41 | + return $outputPath; |
| 42 | + } catch (\Throwable $th) { |
| 43 | + Log::error('Unable to get file subtitles', ['error' => $th->getMessage()]); |
| 44 | + throw $th; |
| 45 | + } |
| 46 | + } |
| 47 | + |
| 48 | + /** |
| 49 | + * Get the relative output path given the subtitle and file extention |
| 50 | + */ |
| 51 | + private function getOutputDir(Subtitle $subtitle, string $ext) { |
| 52 | + $outDir = "data/media/{$subtitle->metadata_uuid}/subtitles"; // Relative output directory |
| 53 | + Storage::disk('local')->makeDirectory($outDir); // Ensure directory exists |
| 54 | + |
| 55 | + return "{$outDir}/{$subtitle->track_id}.{$ext}"; // Add track.ext to get final output address |
| 56 | + } |
| 57 | + |
| 58 | + private function getExtentionFromCodec(string $codec): string { |
| 59 | + return match ($codec) { |
| 60 | + 'subrip' => 'srt', |
| 61 | + 'ass' => 'ass', |
| 62 | + 'ssa' => 'ssa', |
| 63 | + 'webvtt' => 'vtt', |
| 64 | + 'hdmv_pgs_subtitle' => 'sup', |
| 65 | + 'dvd_subtitle' => 'sub', |
| 66 | + default => 'bin', |
| 67 | + }; |
| 68 | + } |
| 69 | +} |
0 commit comments