@@ -83,6 +83,47 @@ const ApiLive = HttpApiBuilder.api(Api).pipe(
8383 ) ,
8484) ;
8585
86+ const resolveRawPreviewKey = ( video : Video . Video ) =>
87+ Effect . gen ( function * ( ) {
88+ const db = yield * Database ;
89+ const [ s3 ] = yield * S3Buckets . getBucketAccess ( video . bucketId ) ;
90+ const [ uploadRecord ] = yield * db . use ( ( db ) =>
91+ db
92+ . select ( { rawFileKey : Db . videoUploads . rawFileKey } )
93+ . from ( Db . videoUploads )
94+ . where ( eq ( Db . videoUploads . videoId , video . id ) ) ,
95+ ) ;
96+
97+ if ( uploadRecord ?. rawFileKey ) {
98+ return uploadRecord . rawFileKey ;
99+ }
100+
101+ if ( video . source . type !== "webMP4" ) {
102+ return yield * Effect . fail ( new HttpApiError . NotFound ( ) ) ;
103+ }
104+
105+ const candidateKeys = [
106+ `${ video . ownerId } /${ video . id } /raw-upload.mp4` ,
107+ `${ video . ownerId } /${ video . id } /raw-upload.webm` ,
108+ ] ;
109+ const headResults = yield * Effect . all (
110+ candidateKeys . map ( ( key ) => s3 . headObject ( key ) . pipe ( Effect . option ) ) ,
111+ { concurrency : "unbounded" } ,
112+ ) ;
113+ for ( const [ index , candidateKey ] of candidateKeys . entries ( ) ) {
114+ const rawHead = headResults [ index ] ;
115+ if (
116+ rawHead &&
117+ Option . isSome ( rawHead ) &&
118+ ( rawHead . value . ContentLength ?? 0 ) > 0
119+ ) {
120+ return candidateKey ;
121+ }
122+ }
123+
124+ return yield * Effect . fail ( new HttpApiError . NotFound ( ) ) ;
125+ } ) ;
126+
86127const getPlaylistResponse = (
87128 video : Video . Video ,
88129 urlParams : ( typeof GetPlaylistParams ) [ "Type" ] ,
@@ -93,20 +134,9 @@ const getPlaylistResponse = (
93134 video . source . type === "desktopMP4" || video . source . type === "webMP4" ;
94135
95136 if ( urlParams . videoType === "raw-preview" ) {
96- const db = yield * Database ;
97- const [ uploadRecord ] = yield * db . use ( ( db ) =>
98- db
99- . select ( { rawFileKey : Db . videoUploads . rawFileKey } )
100- . from ( Db . videoUploads )
101- . where ( eq ( Db . videoUploads . videoId , urlParams . videoId ) ) ,
102- ) ;
103-
104- if ( ! uploadRecord ?. rawFileKey ) {
105- return yield * Effect . fail ( new HttpApiError . NotFound ( ) ) ;
106- }
107-
137+ const rawFileKey = yield * resolveRawPreviewKey ( video ) ;
108138 return yield * s3
109- . getSignedObjectUrl ( uploadRecord . rawFileKey )
139+ . getSignedObjectUrl ( rawFileKey )
110140 . pipe ( Effect . map ( HttpServerResponse . redirect ) ) ;
111141 }
112142
@@ -201,12 +231,17 @@ const getPlaylistResponse = (
201231 s3 . listObjects ( { prefix : audioPrefix , maxKeys : 1 } ) ,
202232 ] ) ;
203233
204- const videoMetadata = yield * s3 . headObject (
205- videoSegment . Contents ?. [ 0 ] ?. Key ?? "" ,
206- ) ;
234+ const videoSegmentKey = videoSegment . Contents ?. [ 0 ] ?. Key ;
235+ if ( ! videoSegmentKey ) {
236+ return yield * Effect . fail ( new HttpApiError . NotFound ( ) ) ;
237+ }
238+
239+ const videoMetadata = yield * s3 . headObject ( videoSegmentKey ) ;
207240 const audioMetadata =
208241 audioSegment ?. KeyCount && audioSegment . KeyCount > 0
209- ? yield * s3 . headObject ( audioSegment . Contents ?. [ 0 ] ?. Key ?? "" )
242+ ? audioSegment . Contents ?. [ 0 ] ?. Key
243+ ? yield * s3 . headObject ( audioSegment . Contents [ 0 ] . Key )
244+ : undefined
210245 : undefined ;
211246
212247 const generatedPlaylist = generateMasterPlaylist (
0 commit comments