@@ -8,6 +8,10 @@ class Ffmpeg extends Process
88{
99 protected string $ startTimestamp = '00:00:00 ' ;
1010
11+ private static bool $ binaryResolved = false ;
12+
13+ private static ?string $ resolvedBinary = null ;
14+
1115 public function startTimestamp (string $ startTimestamp ): self
1216 {
1317 $ this ->startTimestamp = $ startTimestamp ;
@@ -49,10 +53,26 @@ private function buildCommand(string $ffmpegBinary, string $path, string $output
4953 ])->join (' ' );
5054 }
5155
56+ public function available (): bool
57+ {
58+ return filled ($ this ->ffmpegBinary ());
59+ }
60+
5261 public function ffmpegBinary (): ?string
62+ {
63+ if (static ::$ binaryResolved ) {
64+ return static ::$ resolvedBinary ;
65+ }
66+
67+ static ::$ binaryResolved = true ;
68+
69+ return static ::$ resolvedBinary = $ this ->resolveFfmpegBinary ();
70+ }
71+
72+ private function resolveFfmpegBinary (): ?string
5373 {
5474 if ($ binary = config ('statamic.assets.ffmpeg.binary ' )) {
55- return $ binary ;
75+ return is_executable ( $ binary) ? $ binary : null ;
5676 }
5777
5878 $ output = $ this ->run ($ this ->isWindows () ? 'where ffmpeg ' : 'which ffmpeg ' );
@@ -66,8 +86,20 @@ public function ffmpegBinary(): ?string
6686 return null ;
6787 }
6888
69- return str (StringUtilities::normalizeLineEndings (trim ($ output )))
89+ $ resolved = str (StringUtilities::normalizeLineEndings (trim ($ output )))
7090 ->explode ("\n" )
7191 ->first ();
92+
93+ if (! filled ($ resolved ) || ! is_executable ($ resolved )) {
94+ return null ;
95+ }
96+
97+ return $ resolved ;
98+ }
99+
100+ public static function clearBinaryCache (): void
101+ {
102+ static ::$ binaryResolved = false ;
103+ static ::$ resolvedBinary = null ;
72104 }
73105}
0 commit comments