// node import * as fs from 'fs'; import * as path from 'path'; import * as assert from 'assert'; // npm import { v4 as uuid } from 'uuid'; // @ownzones import { Rrtq } from '@ownzones/rrtq'; // app import { Server } from 'http'; import { RedisClient } from 'redis'; import { config } from '../config'; import { CustomAudioTrack, ICustomAudioSegment, PlaylistBuilder, SegmentType, } from '../lib/playlist-builder'; import { Worker } from '../lib/workers/worker'; import { connectApiInit } from './utils/zypline-mock'; import { CacheManager, DynamodbCacheManager, ICacheManager, RedisCacheManager, } from '../lib/cache'; import { SegmentLoader } from '../lib/segment-loader'; import { ffprobe } from './utils/ffmpeg'; import { ensureTestDynamoDBTable, flushDynamoDBTable } from './utils/dynamodb'; import { IComposition } from '../lib/connect-api'; import { TaskResponse } from '../utils/types'; describe('Audio Segments', () => { let cacheManagerInstance: ICacheManager; let connectApi: Server; let rrtq: Rrtq; let worker: Worker; before(async () => { cacheManagerInstance = CacheManager.getInstance(); if (cacheManagerInstance instanceof RedisCacheManager) { await cacheManagerInstance.options.client.flushdbAsync(); } else if (cacheManagerInstance instanceof DynamodbCacheManager) { await ensureTestDynamoDBTable(); await flushDynamoDBTable(); } rrtq = new Rrtq(config); await (rrtq.redisClient as RedisClient).flushdbAsync(); worker = new Worker(config, config.rrtq.audioNamespace); connectApi = connectApiInit(); }); after(async () => { await worker.stop(); connectApi.close(); await rrtq.stop(); cacheManagerInstance.stopCacheGC(); CacheManager.destroyInstance(); }); it('should generate a master playlist with no custom audio tracks', () => { const definition = JSON.parse( fs.readFileSync(path.join(__dirname, './composition-definitions/cd-hpa-cpl.json')).toString(), ) as IComposition; const playlist = PlaylistBuilder.buildPlaylist( definition, '70ad0ea2-5ff8-4c02-8f3d-16f985867151', 5, 'cacheLocation', '1', ); assert.deepStrictEqual(playlist, { type: 'master', mediaPlayList: '#EXTM3U\n#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="eng",NAME="English",AUTOSELECT=YES, DEFAULT=YES,URI="/media-playlist?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=b86ccdd5-2739-4e13-9388-8bed7e0c1d3f"\n#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="eng",NAME="English",AUTOSELECT=YES, DEFAULT=YES,URI="/media-playlist?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=5af33df5-3a1e-4940-a1a5-35d6d10dedee"\n#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=195023,CODECS="avc1.4d0028,mp4a.40.2,stpp.TTML.im1t",AUDIO="audio"\n/media-playlist?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=458e622c-a57b-4436-bff7-f0efe6e4e52a', sourceFile: { id: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', locatorUrl: 's3://oz-zl-test-files/mediaview/src_prores_demux.mov', title: { id: '1234', name: 'test-title', }, }, }); }); it('should generate a master playlist with a custom audio tracks', () => { const definition = JSON.parse( fs.readFileSync(path.join(__dirname, './composition-definitions/cd-hpa-cpl.json')).toString(), ) as IComposition; const customAudioTrack: CustomAudioTrack[] = [ ['5af33df5-3a1e-4940-a1a5-35d6d10dedee', [0, 1], ['FL', 'FR']], ['b86ccdd5-2739-4e13-9388-8bed7e0c1d3f', [0, 3, 4], ['LFE', 'BL', 'BR']], ]; const playlist = PlaylistBuilder.buildPlaylist( definition, '70ad0ea2-5ff8-4c02-8f3d-16f985867151', 5, 'cacheLocation', '1', undefined, undefined, customAudioTrack, ); // console.log(JSON.stringify(playlist, null, 4)); // console.log(playlist); // console.log(playlist.mediaPlayList); assert.deepStrictEqual( playlist, JSON.parse('{"type":"master","mediaPlayList":"#EXTM3U\\n#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\\"audio\\",LANGUAGE=\\"eng\\",NAME=\\"English\\",AUTOSELECT=YES, DEFAULT=YES,URI=\\"/media-playlist?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=customAudio&customAudioTrack=%5B%5B%225af33df5-3a1e-4940-a1a5-35d6d10dedee%22%2C%5B0%2C1%5D%2C%5B%22FL%22%2C%22FR%22%5D%5D%2C%5B%22b86ccdd5-2739-4e13-9388-8bed7e0c1d3f%22%2C%5B0%2C3%2C4%5D%2C%5B%22LFE%22%2C%22BL%22%2C%22BR%22%5D%5D%5D\\"\\n#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=195023,CODECS=\\"avc1.4d0028,mp4a.40.2,stpp.TTML.im1t\\",AUDIO=\\"audio\\"\\n/media-playlist?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=458e622c-a57b-4436-bff7-f0efe6e4e52a","sourceFile":{"id":"e5ed93cc-963b-4059-88da-e55dc48a4ade","locatorUrl":"s3://oz-zl-test-files/mediaview/src_prores_demux.mov","title":{"id":"1234","name":"test-title"}}}'), ); }); it('should generate an audio playlist', () => { const definition = JSON.parse( fs.readFileSync(path.join(__dirname, './composition-definitions/cd-hpa-cpl.json')).toString(), ) as IComposition; const playlist = PlaylistBuilder.buildPlaylist( definition, '70ad0ea2-5ff8-4c02-8f3d-16f985867151', 5, 'cacheLocation', '1', undefined, 'b86ccdd5-2739-4e13-9388-8bed7e0c1d3f', ); // console.log(JSON.stringify(playlist)); assert.deepStrictEqual( JSON.parse(JSON.stringify(playlist)), JSON.parse('{"segments":[{"cacheLocation":"cacheLocation","orgId":"1","fileId":"a1201af7-d9e8-472f-95e3-40f0ec2d2d7e","url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","entryPoint":0,"editUnits":240640,"duration":5.013333333333333,"totalStartTime":0,"startTime":0,"type":"audio","channels":6,"sampleRate":48000,"streamIndex":0,"customChannels":null,"layout":null,"mxfIndexUrl":null},{"cacheLocation":"cacheLocation","orgId":"1","fileId":"a1201af7-d9e8-472f-95e3-40f0ec2d2d7e","url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","entryPoint":240640,"editUnits":240640,"duration":5.013333333333333,"totalStartTime":5.013333333333333,"startTime":5.013333333333333,"type":"audio","channels":6,"sampleRate":48000,"streamIndex":0,"customChannels":null,"layout":null,"mxfIndexUrl":null},{"cacheLocation":"cacheLocation","orgId":"1","fileId":"a1201af7-d9e8-472f-95e3-40f0ec2d2d7e","url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","entryPoint":481280,"editUnits":240640,"duration":5.013333333333333,"totalStartTime":10.026666666666666,"startTime":10.026666666666666,"type":"audio","channels":6,"sampleRate":48000,"streamIndex":0,"customChannels":null,"layout":null,"mxfIndexUrl":null},{"cacheLocation":"cacheLocation","orgId":"1","fileId":"a1201af7-d9e8-472f-95e3-40f0ec2d2d7e","url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","entryPoint":721920,"editUnits":240640,"duration":5.013333333333333,"totalStartTime":15.04,"startTime":15.04,"type":"audio","channels":6,"sampleRate":48000,"streamIndex":0,"customChannels":null,"layout":null,"mxfIndexUrl":null},{"cacheLocation":"cacheLocation","orgId":"1","fileId":"a1201af7-d9e8-472f-95e3-40f0ec2d2d7e","url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","entryPoint":962560,"editUnits":20422,"duration":0.4254583333333333,"totalStartTime":20.05333333333333,"startTime":20.05333333333333,"type":"audio","channels":6,"sampleRate":48000,"streamIndex":0,"customChannels":null,"layout":null,"mxfIndexUrl":null}],"type":"audio","mediaPlayList":"#EXTM3U\\n#EXT-X-VERSION:3\\n#EXT-X-TARGETDURATION:6\\n#EXT-X-MEDIA-SEQUENCE:0\\n#EXTINF:5.013333333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=b86ccdd5-2739-4e13-9388-8bed7e0c1d3f&index=0\\n#EXTINF:5.013333333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=b86ccdd5-2739-4e13-9388-8bed7e0c1d3f&index=1\\n#EXTINF:5.013333333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=b86ccdd5-2739-4e13-9388-8bed7e0c1d3f&index=2\\n#EXTINF:5.013333333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=b86ccdd5-2739-4e13-9388-8bed7e0c1d3f&index=3\\n#EXTINF:0.4254583333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=b86ccdd5-2739-4e13-9388-8bed7e0c1d3f&index=4\\n#EXT-X-ENDLIST","sourceFile":{"id":"e5ed93cc-963b-4059-88da-e55dc48a4ade","locatorUrl":"s3://oz-zl-test-files/mediaview/src_prores_demux.mov","title":{"id":"1234","name":"test-title"}}}'), ); }); it('should generate a custom audio playlist', () => { const definition = JSON.parse( fs.readFileSync(path.join(__dirname, './composition-definitions/cd-hpa-cpl.json')).toString(), ) as IComposition; const customAudioTrack: CustomAudioTrack[] = [ ['5af33df5-3a1e-4940-a1a5-35d6d10dedee', [0, 1], ['FL', 'FR']], ['b86ccdd5-2739-4e13-9388-8bed7e0c1d3f', [0, 3, 4], ['LFE', 'BL', 'BR']], ]; const playlist = PlaylistBuilder.buildPlaylist( definition, '70ad0ea2-5ff8-4c02-8f3d-16f985867151', 5, 'cacheLocation', '1', undefined, 'customAudio', customAudioTrack, ); // console.log(JSON.stringify(playlist, null, 4)); // console.log(JSON.stringify(playlist)); // console.log(playlist.mediaPlayList); assert.deepStrictEqual( JSON.parse(JSON.stringify(playlist)), JSON.parse('{"segments":[{"inputs":[{"streams":{"0":{"startTime":0,"duration":5.013333333333333,"channelsCount":6,"sampleRate":48000,"channelIndices":[0,3,4],"channelLabels":["LFE","BL","BR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","mxfIndexUrl":null},{"streams":{"0":{"startTime":0,"duration":5.013333333333333,"channelsCount":2,"sampleRate":48000,"channelIndices":[0,1],"channelLabels":["FL","FR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_2.0_jp.mxf","mxfIndexUrl":null}],"cacheLocation":"cacheLocation","orgId":"1","totalStartTime":0,"duration":5.013333333333333,"editUnits":240640,"type":"audio"},{"inputs":[{"streams":{"0":{"startTime":5.013333333333333,"duration":5.013333333333333,"channelsCount":6,"sampleRate":48000,"channelIndices":[0,3,4],"channelLabels":["LFE","BL","BR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","mxfIndexUrl":null},{"streams":{"0":{"startTime":5.013333333333333,"duration":5.013333333333333,"channelsCount":2,"sampleRate":48000,"channelIndices":[0,1],"channelLabels":["FL","FR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_2.0_jp.mxf","mxfIndexUrl":null}],"cacheLocation":"cacheLocation","orgId":"1","totalStartTime":5.013333333333333,"duration":5.013333333333333,"editUnits":240640,"type":"audio"},{"inputs":[{"streams":{"0":{"startTime":10.026666666666666,"duration":5.013333333333333,"channelsCount":6,"sampleRate":48000,"channelIndices":[0,3,4],"channelLabels":["LFE","BL","BR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","mxfIndexUrl":null},{"streams":{"0":{"startTime":10.026666666666666,"duration":5.013333333333333,"channelsCount":2,"sampleRate":48000,"channelIndices":[0,1],"channelLabels":["FL","FR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_2.0_jp.mxf","mxfIndexUrl":null}],"cacheLocation":"cacheLocation","orgId":"1","totalStartTime":10.026666666666666,"duration":5.013333333333333,"editUnits":240640,"type":"audio"},{"inputs":[{"streams":{"0":{"startTime":15.04,"duration":5.013333333333333,"channelsCount":6,"sampleRate":48000,"channelIndices":[0,3,4],"channelLabels":["LFE","BL","BR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","mxfIndexUrl":null},{"streams":{"0":{"startTime":15.04,"duration":5.013333333333333,"channelsCount":2,"sampleRate":48000,"channelIndices":[0,1],"channelLabels":["FL","FR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_2.0_jp.mxf","mxfIndexUrl":null}],"cacheLocation":"cacheLocation","orgId":"1","totalStartTime":15.04,"duration":5.013333333333333,"editUnits":240640,"type":"audio"},{"inputs":[{"streams":{"0":{"startTime":20.05333333333333,"duration":0.4254583333333333,"channelsCount":6,"sampleRate":48000,"channelIndices":[0,3,4],"channelLabels":["LFE","BL","BR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf","mxfIndexUrl":null},{"streams":{"0":{"startTime":20.05333333333333,"duration":0.4254583333333333,"channelsCount":2,"sampleRate":48000,"channelIndices":[0,1],"channelLabels":["FL","FR"],"fileId":null,"layout":null}},"url":"s3://oz-zl-test-files/mediaview/audio_2.0_jp.mxf","mxfIndexUrl":null}],"cacheLocation":"cacheLocation","orgId":"1","totalStartTime":20.05333333333333,"duration":0.4254583333333333,"editUnits":20422,"type":"audio"}],"type":"audio","mediaPlayList":"#EXTM3U\\n#EXT-X-VERSION:3\\n#EXT-X-TARGETDURATION:6\\n#EXT-X-MEDIA-SEQUENCE:0\\n#EXTINF:5.013333333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=customAudio&customAudioTrack=%5B%5B%225af33df5-3a1e-4940-a1a5-35d6d10dedee%22%2C%5B0%2C1%5D%2C%5B%22FL%22%2C%22FR%22%5D%5D%2C%5B%22b86ccdd5-2739-4e13-9388-8bed7e0c1d3f%22%2C%5B0%2C3%2C4%5D%2C%5B%22LFE%22%2C%22BL%22%2C%22BR%22%5D%5D%5D&index=0\\n#EXTINF:5.013333333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=customAudio&customAudioTrack=%5B%5B%225af33df5-3a1e-4940-a1a5-35d6d10dedee%22%2C%5B0%2C1%5D%2C%5B%22FL%22%2C%22FR%22%5D%5D%2C%5B%22b86ccdd5-2739-4e13-9388-8bed7e0c1d3f%22%2C%5B0%2C3%2C4%5D%2C%5B%22LFE%22%2C%22BL%22%2C%22BR%22%5D%5D%5D&index=1\\n#EXTINF:5.013333333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=customAudio&customAudioTrack=%5B%5B%225af33df5-3a1e-4940-a1a5-35d6d10dedee%22%2C%5B0%2C1%5D%2C%5B%22FL%22%2C%22FR%22%5D%5D%2C%5B%22b86ccdd5-2739-4e13-9388-8bed7e0c1d3f%22%2C%5B0%2C3%2C4%5D%2C%5B%22LFE%22%2C%22BL%22%2C%22BR%22%5D%5D%5D&index=2\\n#EXTINF:5.013333333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=customAudio&customAudioTrack=%5B%5B%225af33df5-3a1e-4940-a1a5-35d6d10dedee%22%2C%5B0%2C1%5D%2C%5B%22FL%22%2C%22FR%22%5D%5D%2C%5B%22b86ccdd5-2739-4e13-9388-8bed7e0c1d3f%22%2C%5B0%2C3%2C4%5D%2C%5B%22LFE%22%2C%22BL%22%2C%22BR%22%5D%5D%5D&index=3\\n#EXTINF:0.4254583333333333\\n/segment?fileId=70ad0ea2-5ff8-4c02-8f3d-16f985867151&virtualTrackId=customAudio&customAudioTrack=%5B%5B%225af33df5-3a1e-4940-a1a5-35d6d10dedee%22%2C%5B0%2C1%5D%2C%5B%22FL%22%2C%22FR%22%5D%5D%2C%5B%22b86ccdd5-2739-4e13-9388-8bed7e0c1d3f%22%2C%5B0%2C3%2C4%5D%2C%5B%22LFE%22%2C%22BL%22%2C%22BR%22%5D%5D%5D&index=4\\n#EXT-X-ENDLIST","sourceFile":{"id":"e5ed93cc-963b-4059-88da-e55dc48a4ade","locatorUrl":"s3://oz-zl-test-files/mediaview/src_prores_demux.mov","title":{"id":"1234","name":"test-title"}}}'), ); }); it('should generate a ts audio segment with custom channels from an MXF source', async () => { const queue = await rrtq.createQueue( uuid(), { queueTimeout: 3000, taskTimeout: 2000, uniqueTasks: false, namespace: config.rrtq.audioNamespace, }, ); const segmentInfo: ICustomAudioSegment = { inputs: [ { streams: { 0: { startTime: 0, duration: 5, channelsCount: 6, sampleRate: 48000, channelIndices: [0, 3], channelLabels: ['LFE', 'BL'], fileId: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', }, }, url: 's3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf', }, { streams: { 0: { startTime: 0, duration: 5, channelsCount: 6, sampleRate: 48000, channelIndices: [4], channelLabels: ['BR'], fileId: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', }, }, url: 's3://oz-zl-test-files/mediaview/audio_5.1_jp.mxf', }, { streams: { 0: { startTime: 0, duration: 5, channelsCount: 2, sampleRate: 48000, channelIndices: [0, 1], channelLabels: ['FL', 'FR'], fileId: 'e5ed93cc-963b-4059-88da-e55dc48a4ada', }, }, url: 's3://oz-zl-test-files/mediaview/audio_2.0_jp.mxf', }, ], duration: 5, editUnits: 5 * 48000, totalStartTime: 0, type: SegmentType.Audio, cacheLocation: `s3://oz-zl-test-files/mediaview/run/${uuid()}/`, orgId: uuid(), fileId: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', }; segmentInfo.id = SegmentLoader.generateSegmentId(segmentInfo); const sourceFile = { file: { id: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', locatorUrl: 's3://oz-zl-test-files/mediaview/src_prores_demux.mov', title: { id: '1234', name: 'test-title', }, }, }; const transcodingTask = { sourceFile, segment: segmentInfo, }; const task = await queue.addTask(transcodingTask, segmentInfo.id); await queue.waitTasks(); const response = await task.getResponse() as TaskResponse; assert.strictEqual(response.error, false); }); it('should generate a stereo ts audio segment with custom channels', async () => { const queue = await rrtq.createQueue( uuid(), { queueTimeout: 3000, taskTimeout: 2000, uniqueTasks: false, namespace: config.rrtq.audioNamespace, }, ); const segmentInfo: ICustomAudioSegment = { inputs: [ { streams: { 1: { startTime: 0, duration: 1, channelsCount: 1, channelIndices: [0], sampleRate: 48000, channelLabels: ['FL'], fileId: 'e5ed93cc-963b-4059-88da-e55dc48a4ada', }, 2: { startTime: 0, duration: 1, channelsCount: 1, channelIndices: [0], sampleRate: 48000, channelLabels: ['FR'], fileId: 'e5ed93cc-963b-4059-88da-e55dc48a4ada', }, }, url: 's3://oz-zl-test-files/demux/src_prores_demux.mov', }, ], editUnits: 48000, duration: 1, totalStartTime: 0, type: SegmentType.Audio, cacheLocation: `s3://oz-zl-test-files/mediaview/run/${uuid()}/`, orgId: uuid(), fileId: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', }; segmentInfo.id = SegmentLoader.generateSegmentId(segmentInfo); const sourceFile = { file: { id: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', locatorUrl: 's3://oz-zl-test-files/mediaview/src_prores_demux.mov', title: { id: '1234', name: 'test-title', }, }, }; const transcodingTask: any = { sourceFile, segment: segmentInfo, }; const task = await queue.addTask(transcodingTask, segmentInfo.id); await queue.waitTasks(); const response = await task.getResponse() as TaskResponse; assert.strictEqual(response.error, false); }); it('should not generate a segment which ends later than it must', async () => { const queue = await rrtq.createQueue( uuid(), { queueTimeout: 3000, taskTimeout: 2000, uniqueTasks: false, namespace: config.rrtq.audioNamespace, }, ); const segmentInfo: ICustomAudioSegment = { inputs: [ { streams: { 1: { startTime: 1, duration: 0.224, channelsCount: 1, channelIndices: [0], sampleRate: 48000, channelLabels: ['FL'], fileId: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', }, }, url: 's3://oz-zl-test-files/demux/src_prores_demux.mov', }, ], editUnits: 0.224 * 48000, duration: 0.224, totalStartTime: 0, type: SegmentType.Audio, cacheLocation: `s3://oz-zl-test-files/mediaview/run/${uuid()}/`, orgId: uuid(), fileId: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', }; segmentInfo.id = SegmentLoader.generateSegmentId(segmentInfo); const sourceFile = { file: { id: 'e5ed93cc-963b-4059-88da-e55dc48a4ade', locatorUrl: 's3://oz-zl-test-files/mediaview/src_prores_demux.mov', title: { id: '1234', name: 'test-title', }, }, }; const transcodingTask: any = { sourceFile, segment: segmentInfo, }; const task = await queue.addTask(transcodingTask, segmentInfo.id); await queue.waitTasks(); const response = await task.getResponse() as TaskResponse; if (response.error) { assert.fail(response.errorObject); } const audioStream = await ffprobe(response.result.s3Path); assert.ok(audioStream.startTime != null && audioStream.duration != null); assert.ok((audioStream.startTime as number) + Number.parseInt(audioStream.duration as string, 10) < 1.224 + 1e-5); }); });