@@ -42,6 +42,21 @@ public function isAvailable(FileInfo $file): bool {
42
42
return is_string ($ this ->binary );
43
43
}
44
44
45
+ private function connectDirect (File $ file ) {
46
+ // Checks for availability to access the video file directly via HTTP/HTTPS.
47
+ // Returns a string containing URL if available. Only implemented and tested
48
+ // with Amazon S3 currently. In all other cases, return false. ffmpeg
49
+ // supports other protocols so this function may expand in the future.
50
+ $ gddValues = $ file ->getStorage ()->getDirectDownload ($ file ->getName ());
51
+ if (is_array ($ gddValues )) {
52
+ if (array_key_exists ('url ' , $ gddValues )) {
53
+ $ directUrl = str_starts_with ($ gddValues ['url ' ], 'http ' ) ? $ gddValues ['url ' ] : false ;
54
+ return $ directUrl ;
55
+ }
56
+ }
57
+ return false ;
58
+ }
59
+
45
60
/**
46
61
* {@inheritDoc}
47
62
*/
@@ -51,54 +66,60 @@ public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
51
66
if (!$ this ->isAvailable ($ file )) {
52
67
return null ;
53
68
}
54
-
55
69
$ result = null ;
56
- if ($ this ->useTempFile ($ file )) {
57
- // Try downloading 5 MB first, as it's likely that the first frames are present there.
58
- // In some cases this doesn't work, for example when the moov atom is at the
59
- // end of the file, so if it fails we fall back to getting the full file.
60
- // Unless the file is not local (e.g. S3) as we do not want to download the whole (e.g. 37Gb) file
61
- if ($ file ->getStorage ()->isLocal ()) {
62
- $ sizeAttempts = [5242880 , null ];
70
+ $ connectDirect = $ this ->connectDirect ($ file );
71
+ if ($ connectDirect === false ) {
72
+ // If HTTP/HTTPS direct connect is not available, process normally with
73
+ // temp files
74
+ if ($ this ->useTempFile ($ file )) {
75
+ // Try downloading 5 MB first, as it's likely that the first frames are
76
+ // present there. In some cases this doesn't work (e.g. when the
77
+ // moov atom is at the end) so if it fails, fall back to
78
+ // getting the full file, unless the file is not local as we do not want
79
+ // to download the whole (e.g. 37GB) file from remote.
80
+ if ($ file ->getStorage ()->isLocal ()) {
81
+ $ sizeAttempts = [5242880 , null ];
82
+ } else {
83
+ $ sizeAttempts = [5242880 ];
84
+ }
63
85
} else {
64
- $ sizeAttempts = [5242880 ];
86
+ // size is irrelevant, only attempt once
87
+ $ sizeAttempts = [null ];
65
88
}
66
- } else {
67
- // size is irrelevant, only attempt once
68
- $ sizeAttempts = [null ];
69
- }
70
-
71
- foreach ($ sizeAttempts as $ size ) {
72
- $ absPath = $ this ->getLocalFile ($ file , $ size );
73
- if ($ absPath === false ) {
74
- Server::get (LoggerInterface::class)->error (
75
- 'Failed to get local file to generate thumbnail for: ' . $ file ->getPath (),
76
- ['app ' => 'core ' ]
77
- );
78
- return null ;
79
- }
80
-
81
- $ result = $ this ->generateThumbNail ($ maxX , $ maxY , $ absPath , 5 );
82
- if ($ result === null ) {
83
- $ result = $ this ->generateThumbNail ($ maxX , $ maxY , $ absPath , 1 );
84
- if ($ result === null ) {
85
- $ result = $ this ->generateThumbNail ($ maxX , $ maxY , $ absPath , 0 );
89
+
90
+ foreach ($ sizeAttempts as $ size ) {
91
+ $ absPath = $ this ->getLocalFile ($ file , $ size );
92
+ if ($ absPath === false ) {
93
+ Server::get (LoggerInterface::class)->error (
94
+ 'Failed to get local file to generate thumbnail for: ' .
95
+ $ file ->getPath (), ['app ' => 'core ' ]
96
+ );
97
+ return null ;
86
98
}
87
- }
88
99
89
- $ this ->cleanTmpFiles ();
100
+ $ result = ($ this ->generateThumbNail ($ maxX , $ maxY , $ absPath , 5 )) ??
101
+ ($ this ->generateThumbNail ($ maxX , $ maxY , $ absPath , 1 )) ??
102
+ ($ this ->generateThumbNail ($ maxX , $ maxY , $ absPath , 0 ));
103
+
104
+ $ this ->cleanTmpFiles ();
90
105
91
- if ($ result !== null ) {
92
- break ;
106
+ if ($ result !== null ) {
107
+ break ;
108
+ }
93
109
}
110
+ } else {
111
+ // HTTP/HTTPS direct connect is available so pass the URL directly to ffmpeg
112
+ $ result = ($ this ->generateThumbNail ($ maxX , $ maxY , $ connectDirect , 5 )) ??
113
+ ($ this ->generateThumbNail ($ maxX , $ maxY , $ connectDirect , 1 )) ??
114
+ ($ this ->generateThumbNail ($ maxX , $ maxY , $ connectDirect , 0 ));
94
115
}
95
-
96
116
return $ result ;
97
117
}
98
118
99
119
private function useHdr (string $ absPath ): bool {
100
120
// load ffprobe path from configuration, otherwise generate binary path using ffmpeg binary path
101
- $ ffprobe_binary = $ this ->config ->getSystemValue ('preview_ffprobe_path ' , null ) ?? (pathinfo ($ this ->binary , PATHINFO_DIRNAME ) . '/ffprobe ' );
121
+ $ ffprobe_binary = ($ this ->config ->getSystemValue ('preview_ffprobe_path ' , null )) ??
122
+ (pathinfo ($ this ->binary , PATHINFO_DIRNAME ) . '/ffprobe ' );
102
123
// run ffprobe on the video file to get value of "color_transfer"
103
124
$ test_hdr_cmd = [$ ffprobe_binary ,'-select_streams ' , 'v:0 ' ,
104
125
'-show_entries ' , 'stream=color_transfer ' ,
0 commit comments