@@ -218,19 +218,23 @@ beforeAll(async () => {
218218 tempDir = mkdtempSync ( join ( tmpdir ( ) , "cap-real-world-routes-" ) ) ;
219219 for ( const kind of [ "video" , "audio" ] as const ) {
220220 const path = join ( tempDir , `${ kind } -fragmented.mp4` ) ;
221- execFileSync ( "ffmpeg" , [
222- "-v" ,
223- "error" ,
224- "-i" ,
225- TEST_VIDEO_WITH_AUDIO ,
226- "-map" ,
227- kind === "video" ? "0:v:0" : "0:a:0" ,
228- "-c" ,
229- "copy" ,
230- "-movflags" ,
231- "+empty_moov+frag_keyframe+default_base_moof" ,
232- path ,
233- ] ) ;
221+ execFileSync (
222+ "ffmpeg" ,
223+ [
224+ "-v" ,
225+ "error" ,
226+ "-i" ,
227+ TEST_VIDEO_WITH_AUDIO ,
228+ "-map" ,
229+ kind === "video" ? "0:v:0" : "0:a:0" ,
230+ "-c" ,
231+ "copy" ,
232+ "-movflags" ,
233+ "+empty_moov+frag_keyframe+default_base_moof" ,
234+ path ,
235+ ] ,
236+ { stdio : "inherit" } ,
237+ ) ;
234238 const bytes = new Uint8Array ( await Bun . file ( path ) . arrayBuffer ( ) ) ;
235239 const view = new DataView ( bytes . buffer ) ;
236240 let split = 0 ;
@@ -1145,6 +1149,80 @@ describe("media routes real-world integration tests", () => {
11451149 }
11461150 } , 15_000 ) ;
11471151
1152+ test ( "imports a real video and preserves the original bytes before processing" , async ( ) => {
1153+ const response = await app . fetch (
1154+ mediaPostRequest ( "/video/import" , {
1155+ videoId : "direct-import" ,
1156+ userId : "import-owner" ,
1157+ videoUrl : fixtureUrl ( ) ,
1158+ sourcePresignedUrl : uploadUrl ( "import-original.mp4" ) ,
1159+ outputPresignedUrl : uploadUrl ( "import-output.mp4" ) ,
1160+ inputExtension : ".mp4" ,
1161+ maxWidth : 160 ,
1162+ maxHeight : 120 ,
1163+ preset : "ultrafast" ,
1164+ } ) ,
1165+ ) ;
1166+ expect ( response . status ) . toBe ( 200 ) ;
1167+ const { jobId } = ( await response . json ( ) ) as { jobId : string } ;
1168+ try {
1169+ const job = await waitForTerminalJob ( jobId ) ;
1170+ expect ( job . phase ) . toBe ( "complete" ) ;
1171+ expect ( uploadedBytes ( "/uploads/import-original.mp4" ) ) . toEqual (
1172+ new Uint8Array ( await Bun . file ( TEST_VIDEO_WITH_AUDIO ) . arrayBuffer ( ) ) ,
1173+ ) ;
1174+ const metadata = await probeBytesAsMp4 (
1175+ uploadedBytes ( "/uploads/import-output.mp4" ) ,
1176+ "import-output.mp4" ,
1177+ ) ;
1178+ expect ( metadata . videoCodec ) . toBe ( "h264" ) ;
1179+ expect ( metadata . audioCodec ) . toBe ( "aac" ) ;
1180+ expect ( metadata . width ) . toBeLessThanOrEqual ( 160 ) ;
1181+ expect ( [ ...uploadedArtifacts . keys ( ) ] ) . toEqual ( [
1182+ "/uploads/import-original.mp4" ,
1183+ "/uploads/import-output.mp4" ,
1184+ ] ) ;
1185+ } finally {
1186+ deleteJob ( jobId ) ;
1187+ }
1188+ } , 90000 ) ;
1189+
1190+ test ( "fails an import when the original cannot be saved without processing it" , async ( ) => {
1191+ const process = spyOn ( mediaVideo , "processVideo" ) ;
1192+ const response = await app . fetch (
1193+ mediaPostRequest ( "/video/import" , {
1194+ videoId : "failed-import" ,
1195+ userId : "import-owner" ,
1196+ videoUrl : fixtureUrl ( ) ,
1197+ sourcePresignedUrl : `${ baseUrl } /missing-original-destination` ,
1198+ outputPresignedUrl : uploadUrl ( "failed-import-output.mp4" ) ,
1199+ inputExtension : ".mp4" ,
1200+ } ) ,
1201+ ) ;
1202+ expect ( response . status ) . toBe ( 200 ) ;
1203+ const { jobId } = ( await response . json ( ) ) as { jobId : string } ;
1204+ try {
1205+ const job = await waitForTerminalJob ( jobId ) ;
1206+ expect ( job . phase ) . toBe ( "error" ) ;
1207+ expect ( process ) . not . toHaveBeenCalled ( ) ;
1208+ expect ( uploadedArtifacts . size ) . toBe ( 0 ) ;
1209+ } finally {
1210+ deleteJob ( jobId ) ;
1211+ }
1212+ } , 90000 ) ;
1213+
1214+ test ( "rejects imports that omit original storage" , async ( ) => {
1215+ const response = await app . fetch (
1216+ mediaPostRequest ( "/video/import" , {
1217+ videoId : "unsafe-import" ,
1218+ userId : "import-owner" ,
1219+ videoUrl : fixtureUrl ( ) ,
1220+ outputPresignedUrl : uploadUrl ( "unsafe-import.mp4" ) ,
1221+ } ) ,
1222+ ) ;
1223+ expect ( response . status ) . toBe ( 400 ) ;
1224+ } ) ;
1225+
11481226 test ( "retries transient segment downloads and completes a real mux job" , async ( ) => {
11491227 const response = await app . fetch (
11501228 mediaPostRequest ( "/video/mux-segments" , {
0 commit comments