Skip to content

Commit

Permalink
fix: ensure that calculated cue-out duration for audio and video are …
Browse files Browse the repository at this point in the history
…the same
  • Loading branch information
birme committed Apr 4, 2023
1 parent a8053c2 commit 0ebd7af
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 7 deletions.
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ class HLSSpliceVod {
this.playlists[bw].items.PlaylistItem[i].get("cuein")
) {
const cueOut = itemToUpdate.get("cueout");
itemToUpdate.set("cueout", cueOut + adBreakDuration);
itemToUpdate.set("cueout", Math.round(cueOut + adBreakDuration));
}
}
}
Expand Down Expand Up @@ -529,7 +529,7 @@ class HLSSpliceVod {
this.playlistsAudio[g][l].items.PlaylistItem[i].get("cuein")
) {
const cueOut = itemToUpdate.get("cueout");
itemToUpdate.set("cueout", cueOut + adBreakDuration);
itemToUpdate.set("cueout", Math.round(cueOut + adBreakDuration));
}
}
}
Expand Down
77 changes: 73 additions & 4 deletions spec/hls_splice_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,20 @@ describe("HLSSpliceVod with Demuxed Audio Tracks,", () => {
mockBumperAudioManifest = (g, l) => {
return fs.createReadStream(`testvectors/demux/ad1/index_${g}-${l}_a.m3u8`);
};
// MOCK VOD #8 (different fractional audio and video segment duration)
mockAdMasterManifest5 = () => {
return fs.createReadStream("testvectors/demux/ad5/master.m3u8");
};
mockAdMediaManifest5 = (bw) => {
const bwmap = {
4497000: "0",
2497000: "1",
};
return fs.createReadStream(`testvectors/demux/ad5/index_${bwmap[bw]}_v.m3u8`);
};
mockAdAudioManifest5 = (g, l) => {
return fs.createReadStream(`testvectors/demux/ad5/index_${g}-${l}_a.m3u8`);
};
});

it("can prepend a baseurl on each segment", (done) => {
Expand Down Expand Up @@ -1221,6 +1235,61 @@ describe("HLSSpliceVod with Demuxed Audio Tracks,", () => {
});
});

it("ensures that cue out duration is the same for video and audio", (done) => {
const mockVod = new HLSSpliceVod("http://mock.com/mock.m3u8", { merge: true });
mockVod
.load(mockMasterManifest1b, mockMediaManifest1b, mockAudioManifest1b)
.then(() => {
return mockVod.insertAdAt(
0,
"http://mock.com/ad/mockad.m3u8",
mockAdMasterManifest,
mockAdMediaManifest,
mockAdAudioManifest
);
})
.then(() => {
return mockVod.insertAdAt(
0,
"http://mock.com/ad/mockad.m3u8",
mockAdMasterManifest3,
mockAdMediaManifest3,
mockAdAudioManifest3
);
})
.then(() => {
// This one will go first
return mockVod.insertAdAt(
0,
"http://mock.com/ad/mockad.m3u8",
mockAdMasterManifest5,
mockAdMediaManifest5,
mockAdAudioManifest5
);
})
.then(() => {
return mockVod.insertBumper(
"http://mock.com/ad/mockbumper.m3u8",
mockBumperMasterManifest,
mockBumperMediaManifest,
mockBumperAudioManifest
);
})
.then(() => {
const m3u8 = mockVod.getMediaManifest(4497000);
let lines = m3u8.split("\n");
expect(lines[1]).toEqual("#EXT-X-TARGETDURATION:8");
expect(lines[10 + 8]).toEqual("#EXT-X-CUE-OUT:DURATION=23");
expect(lines[lines.length - 2]).toEqual("#EXT-X-ENDLIST");
const m3u8Audio = mockVod.getAudioManifest("mono", "en");
lines = m3u8Audio.split("\n");
expect(lines[1]).toEqual("#EXT-X-TARGETDURATION:8");
expect(lines[10 + 8]).toEqual("#EXT-X-CUE-OUT:DURATION=23");
expect(lines[lines.length - 2]).toEqual("#EXT-X-ENDLIST");
done();
});
});

it("handles target duration with video bumper and no ads", (done) => {
const mockVod = new HLSSpliceVod("http://mock.com/mock.m3u8", { merge: true });
mockVod
Expand Down Expand Up @@ -1666,7 +1735,7 @@ test-audio=256000-6.m4s`;
let lines = m3u8.split("\n");
expect(lines[8]).toEqual(`#EXT-X-MAP:URI="http://mock.com/ad/mock-ad3-video=2525000.m4s"`);
expect(lines[9]).toEqual(`#EXT-X-DISCONTINUITY`);
expect(lines[10]).toEqual(`#EXT-X-CUE-OUT:DURATION=17.16`);
expect(lines[10]).toEqual(`#EXT-X-CUE-OUT:DURATION=17`);
expect(lines[12]).toEqual(`http://mock.com/ad/mock-ad3-video=2525000-1.m4s`);
expect(lines[13]).toEqual(`#EXT-X-MAP:URI="http://mock.com/ad/mock-ad-video=2525000.m4s"`);
expect(lines[14]).toEqual(`#EXT-X-DISCONTINUITY`);
Expand All @@ -1680,7 +1749,7 @@ test-audio=256000-6.m4s`;
const linesAudio = m3u8Audio.split("\n");
expect(linesAudio[8]).toEqual(`#EXT-X-MAP:URI="http://mock.com/ad/mock-ad3-audio=256000.m4s"`);
expect(linesAudio[9]).toEqual(`#EXT-X-DISCONTINUITY`);
expect(linesAudio[10]).toEqual(`#EXT-X-CUE-OUT:DURATION=18.3466`);
expect(linesAudio[10]).toEqual(`#EXT-X-CUE-OUT:DURATION=18`);
expect(linesAudio[12]).toEqual(`http://mock.com/ad/mock-ad3-audio=256000-1.m4s`);
expect(linesAudio[15]).toEqual(`#EXT-X-MAP:URI="http://mock.com/ad/mock-ad-audio=256000.m4s"`);
expect(linesAudio[16]).toEqual(`#EXT-X-DISCONTINUITY`);
Expand Down Expand Up @@ -1845,12 +1914,12 @@ test-audio=256000-6.m4s`;
const m3u8 = mockVod.getMediaManifest(4497000);
let lines = m3u8.split("\n");
expect(lines[6]).toEqual("#EXT-X-TARGETDURATION:5");
expect(lines[21]).toEqual("#EXT-X-CUE-OUT:DURATION=22.16");
expect(lines[21]).toEqual("#EXT-X-CUE-OUT:DURATION=22");
expect(lines[lines.length - 2]).toEqual("#EXT-X-ENDLIST");
const m3u8Audio = mockVod.getAudioManifest("stereo", "sv");
lines = m3u8Audio.split("\n");
expect(lines[6]).toEqual("#EXT-X-TARGETDURATION:4");
expect(lines[27]).toEqual("#EXT-X-CUE-OUT:DURATION=23.7599");
expect(lines[27]).toEqual("#EXT-X-CUE-OUT:DURATION=24");
expect(lines[lines.length - 2]).toEqual("#EXT-X-ENDLIST");
done();
});
Expand Down
2 changes: 1 addition & 1 deletion spec/integration_tests_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe("HLSSpliceVod", () => {
});
});

it("can download and parse an HLS VOD with separate audio and subtitles", (done) => {
xit("can download and parse an HLS VOD with separate audio and subtitles", (done) => {
const hlsVod = new HLSSpliceVod(
"https://lbs-usp-hls-vod.cmore.se/vod/81ed4/a5fa1fw0uoq(12535120_ISMUSP).ism/a5fa1fw0uoq(12535120_ISMUSP).m3u8?hls_no_multiplex=false"
);
Expand Down
9 changes: 9 additions & 0 deletions testvectors/demux/ad5/index_0_v.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-TARGETDURATION:5
#EXT-X-ALLOW-CACHE:YES
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:5.000,
ad1_0_av.ts
#EXT-X-ENDLIST
9 changes: 9 additions & 0 deletions testvectors/demux/ad5/index_1_v.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-TARGETDURATION:5
#EXT-X-ALLOW-CACHE:YES
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:5.000,
ad1_1_av.ts
#EXT-X-ENDLIST
9 changes: 9 additions & 0 deletions testvectors/demux/ad5/index_mono-en_a.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-TARGETDURATION:5
#EXT-X-ALLOW-CACHE:YES
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:4.920,
ad1_men_a.ts
#EXT-X-ENDLIST
9 changes: 9 additions & 0 deletions testvectors/demux/ad5/index_mono-sv_a.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-TARGETDURATION:5
#EXT-X-ALLOW-CACHE:YES
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:4.920,
ad1_msv_a.ts
#EXT-X-ENDLIST
9 changes: 9 additions & 0 deletions testvectors/demux/ad5/index_stereo-en_a.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-TARGETDURATION:5
#EXT-X-ALLOW-CACHE:YES
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:4.920,
ad1_sen_a.ts
#EXT-X-ENDLIST
9 changes: 9 additions & 0 deletions testvectors/demux/ad5/index_stereo-sv_a.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-TARGETDURATION:5
#EXT-X-ALLOW-CACHE:YES
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:4.920,
ad1_ssv_a.ts
#EXT-X-ENDLIST
9 changes: 9 additions & 0 deletions testvectors/demux/ad5/master.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=4497000,RESOLUTION=1280x720,CODECS="avc1.77.30, mp4a.40.2",CLOSED-CAPTIONS=NONE,AUDIO="mono"
index_0_v.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2497000,RESOLUTION=1024x576,CODECS="avc1.77.30, mp4a.40.2",CLOSED-CAPTIONS=NONE,AUDIO="stereo"
index_1_v.m3u8
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="mono",LANGUAGE="sv",NAME="Swedish",AUTOSELECT=YES,DEFAULT=YES,URI="index_mono-sv_a.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="mono",LANGUAGE="en",NAME="English",AUTOSELECT=NO,DEFAULT=NO,URI="index_mono-en_a.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="stereo",LANGUAGE="sv",NAME="Swedish",AUTOSELECT=YES,DEFAULT=YES,URI="index_stereo-sv_a.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="stereo",LANGUAGE="en",NAME="English",AUTOSELECT=NO,DEFAULT=NO,URI="index_stereo-en_a.m3u8"

0 comments on commit 0ebd7af

Please sign in to comment.