From 8ae79826999d16d4c3e7a316b584c7695b098f2a Mon Sep 17 00:00:00 2001 From: Vitaly Gashkov Date: Wed, 27 Nov 2024 12:27:34 +0500 Subject: [PATCH] refactor: try get content type via codecs, add bitmovin parsing test with audio protection --- lib/audio.js | 9 ++++---- lib/dash.js | 25 ++++++++++---------- lib/subtitle.js | 9 ++++---- lib/video.js | 9 ++++---- test/axinom.test.js | 4 ++++ test/bitmovin.mpd | 54 +++++++++++++++++++++++++++++++++++++++++++ test/bitmovin.test.js | 19 +++++++++++++++ 7 files changed, 102 insertions(+), 27 deletions(-) create mode 100644 test/bitmovin.mpd create mode 100644 test/bitmovin.test.js diff --git a/lib/audio.js b/lib/audio.js index de46198..a9b77cc 100644 --- a/lib/audio.js +++ b/lib/audio.js @@ -50,12 +50,11 @@ const parseAudioCodec = (codecs) => { ); }; -const isAudioCodec = (codecs) => { +const tryParseAudioCodec = (codecs) => { try { - parseAudioCodec(codecs); - return true; + return parseAudioCodec(codecs); } catch (e) { - return false; + return null; } }; @@ -142,7 +141,7 @@ const createAudioTrack = ({ module.exports = { AUDIO_CODECS, parseAudioCodec, - isAudioCodec, + tryParseAudioCodec, createAudioTrack, getDolbyDigitalPlusComplexityIndex, checkIsDescriptive, diff --git a/lib/dash.js b/lib/dash.js index 98fbab2..1ac581f 100644 --- a/lib/dash.js +++ b/lib/dash.js @@ -4,20 +4,20 @@ const xml = require('./xml'); const { parseDuration, isLanguageTagValid } = require('./util'); const { parseVideoCodec, - isVideoCodec, + tryParseVideoCodec, parseDynamicRange, createVideoTrack, } = require('./video'); const { parseAudioCodec, - isAudioCodec, + tryParseAudioCodec, createAudioTrack, getDolbyDigitalPlusComplexityIndex, checkIsDescriptive, } = require('./audio'); const { parseSubtitleCodec, - isSubtitleCodec, + tryParseSubtitleCodec, checkIsClosedCaption, checkIsSdh, checkIsForced, @@ -79,23 +79,24 @@ const parseBaseUrl = (manifestUrl, mpd, period, representation) => { return baseUrl; }; +const getTrackTypeByCodecs = (codecs) => { + if (tryParseVideoCodec(codecs)) return 'video'; + else if (tryParseAudioCodec(codecs)) return 'audio'; + else if (tryParseSubtitleCodec(codecs)) return 'text'; + return null; +}; + const parseContentTypes = (representation) => { const codecs = representation.get('codecs'); - const codecsType = isVideoCodec(codecs) - ? 'video' - : isAudioCodec(codecs) - ? 'audio' - : isSubtitleCodec(codecs) - ? 'text' - : null; const mimeType = representation.get('mimeType'); + const contentTypeByCodecs = getTrackTypeByCodecs(codecs); const contentType = - codecsType || representation.get('contentType') || mimeType?.split('/')[0]; + representation.get('contentType') || mimeType?.split('/')[0]; if (!contentType && !mimeType) throw new Error( 'Unable to determine the format of a Representation, cannot continue...', ); - return { contentType, mimeType }; + return { contentType: contentTypeByCodecs || contentType, mimeType }; }; const parseCodecs = (representation, contentType, mimeType) => { diff --git a/lib/subtitle.js b/lib/subtitle.js index b9c555d..04c978a 100644 --- a/lib/subtitle.js +++ b/lib/subtitle.js @@ -51,12 +51,11 @@ const parseSubtitleCodec = (codecs) => { ); }; -const isSubtitleCodec = (codecs) => { +const tryParseSubtitleCodec = (codecs) => { try { - parseSubtitleCodec(codecs); - return true; + return parseSubtitleCodec(codecs); } catch (e) { - return false; + return null; } }; @@ -129,7 +128,7 @@ const createSubtitleTrack = ({ module.exports = { parseSubtitleCodec, - isSubtitleCodec, + tryParseSubtitleCodec, checkIsClosedCaption, checkIsSdh, checkIsForced, diff --git a/lib/video.js b/lib/video.js index fe25840..41bf5df 100644 --- a/lib/video.js +++ b/lib/video.js @@ -153,12 +153,11 @@ const parseVideoCodec = (codecs) => { ); }; -const isVideoCodec = (codecs) => { +const tryParseVideoCodec = (codecs) => { try { - parseVideoCodec(codecs); - return true; + return parseVideoCodec(codecs); } catch (e) { - return false; + return null; } }; @@ -194,7 +193,7 @@ const parseDynamicRange = ( module.exports = { parseVideoCodec, - isVideoCodec, + tryParseVideoCodec, parseDynamicRange, createVideoTrack, VIDEO_CODECS, diff --git a/test/axinom.test.js b/test/axinom.test.js index 9131320..b97bf3d 100644 --- a/test/axinom.test.js +++ b/test/axinom.test.js @@ -16,5 +16,9 @@ test('axinom manifest parsing', async () => { 'https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/5/1.m4s', ); + const firstSubtitleTrack = manifest.tracks.subtitles[0]; + strictEqual(firstSubtitleTrack.codec, 'WVTT'); + strictEqual(firstSubtitleTrack.language, 'en'); + strictEqual(manifest.tracks.all.length, 23); }); diff --git a/test/bitmovin.mpd b/test/bitmovin.mpd new file mode 100644 index 0000000..1adfcb7 --- /dev/null +++ b/test/bitmovin.mpd @@ -0,0 +1,54 @@ + + + + + + + + + AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA== + + + + + + AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA== + + + + + + AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA== + + + + + + AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA== + + + + + + AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA== + + + + + + AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA== + + + + + + + + + + AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA== + + + + + diff --git a/test/bitmovin.test.js b/test/bitmovin.test.js new file mode 100644 index 0000000..0a96a49 --- /dev/null +++ b/test/bitmovin.test.js @@ -0,0 +1,19 @@ +const { test } = require('node:test'); +const { strictEqual } = require('node:assert'); +const { parse } = require('../dasha'); +const { load } = require('./utils'); + +test('bitmovin manifest parsing', async () => { + const url = + 'https://cdn.bitmovin.com/content/assets/art-of-motion_drm/mpds/11331.mpd'; + const text = load('bitmovin.mpd'); + const manifest = await parse(text, url); + + const firstAudioTrack = manifest.tracks.audios[0]; + strictEqual( + firstAudioTrack.protection.widevine.pssh, + 'AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA==', + ); + + strictEqual(manifest.tracks.all.length, 7); +});