mpd-parser
Advanced tools
Comparing version 0.7.0 to 0.8.0-0
@@ -1,2 +0,2 @@ | ||
/*! @name mpd-parser @version 0.7.0 @license Apache-2.0 */ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("global/window")):"function"==typeof define&&define.amd?define(["exports","global/window"],e):e(t.mpdParser={},t.window)}(this,function(t,e){"use strict";e=e&&e.hasOwnProperty("default")?e.default:e;var r=function(t){return!!t&&"object"==typeof t},n=function t(){for(var e=arguments.length,n=new Array(e),i=0;i<e;i++)n[i]=arguments[i];return n.reduce(function(e,n){return Object.keys(n).forEach(function(i){Array.isArray(e[i])&&Array.isArray(n[i])?e[i]=e[i].concat(n[i]):r(e[i])&&r(n[i])?e[i]=t(e[i],n[i]):e[i]=n[i]}),e},{})},i=function(t){return t.reduce(function(t,e){return t.concat(e)},[])},a=function(t){if(!t.length)return[];for(var e=[],r=0;r<t.length;r++)e.push(t[r]);return e},u=function(t){var e;return(e=t.reduce(function(t,e){var r,n=e.attributes.id+(e.attributes.lang||"");t[n]?(e.segments[0].discontinuity=!0,(r=t[n].segments).push.apply(r,e.segments),e.attributes.contentProtection&&(t[n].attributes.contentProtection=e.attributes.contentProtection)):t[n]=e;return t},{}),Object.keys(e).map(function(t){return e[t]})).map(function(t){var e,r;return t.discontinuityStarts=(e=t.segments,r="discontinuity",e.reduce(function(t,e,n){return e[r]&&t.push(n),t},[])),t})},o=function(t){var e,r=t.attributes,n=t.segments,i={attributes:(e={NAME:r.id,AUDIO:"audio",SUBTITLES:"subs",RESOLUTION:{width:r.width,height:r.height},CODECS:r.codecs,BANDWIDTH:r.bandwidth},e["PROGRAM-ID"]=1,e),uri:"",endList:"static"===(r.type||"static"),timeline:r.periodIndex,resolvedUri:"",targetDuration:r.duration,segments:n,mediaSequence:n.length?n[0].number:1};return r.contentProtection&&(i.contentProtection=r.contentProtection),i};"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var s,c=(function(t,e){var r,n,i,a,u;r=/^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/?#]*)?((?:[^\/\?#]*\/)*.*?)??(;.*?)?(\?.*?)?(#.*?)?$/,n=/^([^\/?#]*)(.*)$/,i=/(?:\/|^)\.(?=\/)/g,a=/(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g,u={buildAbsoluteURL:function(t,e,r){if(r=r||{},t=t.trim(),!(e=e.trim())){if(!r.alwaysNormalize)return t;var i=u.parseURL(t);if(!i)throw new Error("Error trying to parse base URL.");return i.path=u.normalizePath(i.path),u.buildURLFromParts(i)}var a=u.parseURL(e);if(!a)throw new Error("Error trying to parse relative URL.");if(a.scheme)return r.alwaysNormalize?(a.path=u.normalizePath(a.path),u.buildURLFromParts(a)):e;var o=u.parseURL(t);if(!o)throw new Error("Error trying to parse base URL.");if(!o.netLoc&&o.path&&"/"!==o.path[0]){var s=n.exec(o.path);o.netLoc=s[1],o.path=s[2]}o.netLoc&&!o.path&&(o.path="/");var c={scheme:o.scheme,netLoc:a.netLoc,path:null,params:a.params,query:a.query,fragment:a.fragment};if(!a.netLoc&&(c.netLoc=o.netLoc,"/"!==a.path[0]))if(a.path){var d=o.path,l=d.substring(0,d.lastIndexOf("/")+1)+a.path;c.path=u.normalizePath(l)}else c.path=o.path,a.params||(c.params=o.params,a.query||(c.query=o.query));return null===c.path&&(c.path=r.alwaysNormalize?u.normalizePath(a.path):a.path),u.buildURLFromParts(c)},parseURL:function(t){var e=r.exec(t);return e?{scheme:e[1]||"",netLoc:e[2]||"",path:e[3]||"",params:e[4]||"",query:e[5]||"",fragment:e[6]||""}:null},normalizePath:function(t){for(t=t.split("").reverse().join("").replace(i,"");t.length!==(t=t.replace(a,"")).length;);return t.split("").reverse().join("")},buildURLFromParts:function(t){return t.scheme+t.netLoc+t.path+t.params+t.query+t.fragment}},t.exports=u}(s={exports:{}},s.exports),s.exports),d=function(t,r){return/^[a-z]+:/i.test(r)?r:(/\/\//i.test(t)||(t=c.buildAbsoluteURL(e.location.href,t)),c.buildAbsoluteURL(t,r))},l=function(t){var e=t.baseUrl,r=void 0===e?"":e,n=t.source,i=void 0===n?"":n,a=t.range,u=void 0===a?"":a,o={uri:i,resolvedUri:d(r||"",i)};if(u){var s=u.split("-"),c=parseInt(s[0],10),l=parseInt(s[1],10);o.byterange={length:l-c,offset:c}}return o},m=function(t,e,r){var n=t.NOW,i=t.clientOffset,a=t.availabilityStartTime,u=t.timescale,o=void 0===u?1:u,s=t.start,c=void 0===s?0:s,d=t.minimumUpdatePeriod,l=(n+i)/1e3+(void 0===d?0:d)-(a+c);return Math.ceil((l*o-e)/r)},f=function(t,e){for(var r=t.type,n=void 0===r?"static":r,i=t.minimumUpdatePeriod,a=void 0===i?0:i,u=t.media,o=void 0===u?"":u,s=t.sourceDuration,c=t.timescale,d=void 0===c?1:c,l=t.startNumber,f=void 0===l?1:l,p=t.periodIndex,h=[],v=-1,b=0;b<e.length;b++){var g=e[b],U=g.d,y=g.r||0,I=g.t||0;v<0&&(v=I),I&&I>v&&(v=I);var D=void 0;if(y<0){var w=b+1;D=w===e.length?"dynamic"===n&&a>0&&o.indexOf("$Number$")>0?m(t,v,U):(s*d-v)/U:(e[w].t-v)/U}else D=y+1;for(var L=f+h.length+D,E=f+h.length;E<L;)h.push({number:E,duration:U/d,time:v,timeline:p}),v+=U,E++}return h},p={static:function(t){var e=t.duration,r=t.timescale,n=void 0===r?1:r,i=t.sourceDuration;return{start:0,end:Math.ceil(i/(e/n))}},dynamic:function(t){var e=t.NOW,r=t.clientOffset,n=t.availabilityStartTime,i=t.timescale,a=void 0===i?1:i,u=t.duration,o=t.start,s=void 0===o?0:o,c=t.minimumUpdatePeriod,d=void 0===c?0:c,l=t.timeShiftBufferDepth,m=void 0===l?1/0:l,f=(e+r)/1e3,p=n+s,h=f+d-p,v=Math.ceil(h*a/u),b=Math.floor((f-p-m)*a/u),g=Math.floor((f-p)*a/u);return{start:Math.max(0,b),end:Math.min(v,g)}}},h=function(t){var e=t.type,r=void 0===e?"static":e,n=t.duration,i=t.timescale,a=void 0===i?1:i,u=t.sourceDuration,o=p[r](t),s=function(t,e){for(var r=[],n=t;n<e;n++)r.push(n);return r}(o.start,o.end).map(function(t){return function(e,r){var n=t.duration,i=t.timescale,a=void 0===i?1:i,u=t.periodIndex,o=t.startNumber;return{number:(void 0===o?1:o)+e,duration:n/a,timeline:u,time:r*n}}}(t));if("static"===r){var c=s.length-1;s[c].duration=u-n/a*c}return s},v=/\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g,b=function(t,e){return t.replace(v,function(t){return function(e,r,n,i){if("$$"===e)return"$";if(void 0===t[r])return e;var a=""+t[r];return"RepresentationID"===r?a:(i=n?parseInt(i,10):1,a.length>=i?a:""+new Array(i-a.length+1).join("0")+a)}}(e))},g=function(t,e){var r={RepresentationID:t.id,Bandwidth:t.bandwidth||0},n=t.initialization,i=void 0===n?{sourceURL:"",range:""}:n,a=l({baseUrl:t.baseUrl,source:b(i.sourceURL,r),range:i.range});return function(t,e){return t.duration||e?t.duration?h(t):f(t,e):[{number:t.startNumber||1,duration:t.sourceDuration,time:0,timeline:t.periodIndex}]}(t,e).map(function(e){r.Number=e.number,r.Time=e.time;var n=b(t.media||"",r);return{uri:n,timeline:e.timeline,duration:e.duration,resolvedUri:d(t.baseUrl||"",n),map:a,number:e.number}})},U="INVALID_NUMBER_OF_PERIOD",y="DASH_EMPTY_MANIFEST",I="DASH_INVALID_XML",D="NO_BASE_URL",w="SEGMENT_TIME_UNSPECIFIED",L="UNSUPPORTED_UTC_TIMING_SCHEME",E=function(t,e){var r=t.duration,n=t.segmentUrls,i=void 0===n?[]:n;if(!r&&!e||r&&e)throw new Error(w);var a,u=i.map(function(e){return function(t,e){var r=t.baseUrl,n=t.initialization,i=void 0===n?{}:n,a=l({baseUrl:r,source:i.sourceURL,range:i.range}),u=l({baseUrl:r,source:e.media,range:e.mediaRange});return u.map=a,u}(t,e)});return r&&(a=h(t)),e&&(a=f(t,e)),a.map(function(t,e){if(u[e]){var r=u[e];return r.timeline=t.timeline,r.duration=t.duration,r.number=t.number,r}}).filter(function(t){return t})},P=function(t){var e=t.baseUrl,r=t.initialization,n=void 0===r?{}:r,i=t.sourceDuration,a=t.timescale,u=void 0===a?1:a,o=t.indexRange,s=void 0===o?"":o,c=t.duration;if(!e)throw new Error(D);var d=l({baseUrl:e,source:n.sourceURL,range:n.range}),m=l({baseUrl:e,source:e,range:s});if(m.map=d,c){var f=h(t);f.length&&(m.duration=f[0].duration,m.timeline=f[0].timeline)}else i&&(m.duration=i/u,m.timeline=0);return m.number=0,[m]},R=function(t){var e,r,i=t.attributes,a=t.segmentInfo;if(a.template?(r=g,e=n(i,a.template)):a.base?(r=P,e=n(i,a.base)):a.list&&(r=E,e=n(i,a.list)),!r)return{attributes:i};var u=r(e,a.timeline);if(e.duration){var o=e,s=o.duration,c=o.timescale,d=void 0===c?1:c;e.duration=s/d}else u.length?e.duration=u.reduce(function(t,e){return Math.max(t,Math.ceil(e.duration))},0):e.duration=0;return{attributes:e,segments:u}},T=function(t,e){return a(t.childNodes).filter(function(t){return t.tagName===e})},N=function(t){return t.textContent.trim()},S=function(t){var e=/P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/.exec(t);if(!e)return 0;var r=e.slice(1),n=r[0],i=r[1],a=r[2],u=r[3],o=r[4],s=r[5];return 31536e3*parseFloat(n||0)+2592e3*parseFloat(i||0)+86400*parseFloat(a||0)+3600*parseFloat(u||0)+60*parseFloat(o||0)+parseFloat(s||0)},A={mediaPresentationDuration:function(t){return S(t)},availabilityStartTime:function(t){return/^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/.test(e=t)&&(e+="Z"),Date.parse(e)/1e3;var e},minimumUpdatePeriod:function(t){return S(t)},timeShiftBufferDepth:function(t){return S(t)},start:function(t){return S(t)},width:function(t){return parseInt(t,10)},height:function(t){return parseInt(t,10)},bandwidth:function(t){return parseInt(t,10)},startNumber:function(t){return parseInt(t,10)},timescale:function(t){return parseInt(t,10)},duration:function(t){var e=parseInt(t,10);return isNaN(e)?S(t):e},d:function(t){return parseInt(t,10)},t:function(t){return parseInt(t,10)},r:function(t){return parseInt(t,10)},DEFAULT:function(t){return t}},O=function(t){return t&&t.attributes?a(t.attributes).reduce(function(t,e){var r=A[e.name]||A.DEFAULT;return t[e.name]=r(e.value),t},{}):{}};var x={"urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b":"org.w3.clearkey","urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed":"com.widevine.alpha","urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":"com.microsoft.playready","urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb":"com.adobe.primetime"},M=function(t,e){return e.length?i(t.map(function(t){return e.map(function(e){return d(t,N(e))})})):t},z=function(t){var e=T(t,"SegmentTemplate")[0],r=T(t,"SegmentList")[0],i=r&&T(r,"SegmentURL").map(function(t){return n({tag:"SegmentURL"},O(t))}),a=T(t,"SegmentBase")[0],u=r||e,o=u&&T(u,"SegmentTimeline")[0],s=r||a||e,c=s&&T(s,"Initialization")[0],d=e&&O(e);d&&c?d.initialization=c&&O(c):d&&d.initialization&&(d.initialization={sourceURL:d.initialization});var l={template:d,timeline:o&&T(o,"S").map(function(t){return O(t)}),list:r&&n(O(r),{segmentUrls:i,initialization:O(c)}),base:a&&n(O(a),{initialization:O(c)})};return Object.keys(l).forEach(function(t){l[t]||delete l[t]}),l},B=function(t){return t.reduce(function(t,r){var n=O(r),i=x[n.schemeIdUri];if(i){t[i]={attributes:n};var a=T(r,"cenc:pssh")[0];if(a){var u=N(a),o=u&&function(t){for(var r=e.atob(t),n=new Uint8Array(r.length),i=0;i<r.length;i++)n[i]=r.charCodeAt(i);return n}(u);t[i].pssh=o}}return t},{})},C=function(t,e,r){return function(a){var u=O(a),o=M(e,T(a,"BaseURL")),s=T(a,"Role")[0],c={role:O(s)},d=n(t,u,c),l=B(T(a,"ContentProtection"));Object.keys(l).length&&(d=n(d,{contentProtection:l}));var m=z(a),f=T(a,"Representation"),p=n(r,m);return i(f.map(function(t,e,r){return function(i){var a=T(i,"BaseURL"),u=M(e,a),o=n(t,O(i)),s=z(i);return u.map(function(t){return{segmentInfo:n(r,s),attributes:n(o,{baseUrl:t})}})}}(d,o,p)))}},F=function(t,r){void 0===r&&(r={});var a=r,u=a.manifestUri,o=void 0===u?"":u,s=a.NOW,c=void 0===s?Date.now():s,d=a.clientOffset,l=void 0===d?0:d,m=T(t,"Period");if(!m.length)throw new Error(U);var f=O(t),p=M([o],T(t,"BaseURL"));return f.sourceDuration=f.mediaPresentationDuration||0,f.NOW=c,f.clientOffset=l,i(m.map(function(t,r){return function(a,u){var o=M(r,T(a,"BaseURL")),s=O(a),c=parseInt(s.id,10),d=e.isNaN(c)?u:c,l=n(t,{periodIndex:d}),m=T(a,"AdaptationSet"),f=z(a);return i(m.map(C(l,o,f)))}}(f,p)))},_=function(t){if(""===t)throw new Error(y);var r=(new e.DOMParser).parseFromString(t,"application/xml"),n=r&&"MPD"===r.documentElement.tagName?r.documentElement:null;if(!n||n&&n.getElementsByTagName("parsererror").length>0)throw new Error(I);return n};t.VERSION="0.7.0",t.parse=function(t,e){return function(t){var e;if(!t.length)return{};var r=t[0].attributes,n=r.sourceDuration,i=r.minimumUpdatePeriod,a=void 0===i?0:i,s=u(t.filter(function(t){var e=t.attributes;return"video/mp4"===e.mimeType||"video"===e.contentType})).map(o),c=u(t.filter(function(t){var e=t.attributes;return"audio/mp4"===e.mimeType||"audio"===e.contentType})),d=t.filter(function(t){var e=t.attributes;return"text/vtt"===e.mimeType||"text"===e.contentType}),l={allowCache:!0,discontinuityStarts:[],segments:[],endList:!0,mediaGroups:(e={AUDIO:{},VIDEO:{}},e["CLOSED-CAPTIONS"]={},e.SUBTITLES={},e),uri:"",duration:n,playlists:s,minimumUpdatePeriod:1e3*a};return c.length&&(l.mediaGroups.AUDIO.audio=c.reduce(function(t,e){var r=e.attributes.role&&e.attributes.role.value||"main",n=e.attributes.lang||"",i="main";return n&&(i=e.attributes.lang+" ("+r+")"),t[i]&&t[i].playlists[0].attributes.BANDWIDTH>e.attributes.bandwidth?t:(t[i]={language:n,autoselect:!0,default:"main"===r,playlists:[function(t){var e,r=t.attributes,n=t.segments,i={attributes:(e={NAME:r.id,BANDWIDTH:r.bandwidth,CODECS:r.codecs},e["PROGRAM-ID"]=1,e),uri:"",endList:"static"===(r.type||"static"),timeline:r.periodIndex,resolvedUri:"",targetDuration:r.duration,segments:n,mediaSequence:n.length?n[0].number:1};return r.contentProtection&&(i.contentProtection=r.contentProtection),i}(e)],uri:""},t)},{})),d.length&&(l.mediaGroups.SUBTITLES.subs=function(t){return t.reduce(function(t,e){var r,n,i,a,u=e.attributes.lang||"text";return t[u]?t:(t[u]={language:u,default:!1,autoselect:!1,playlists:[(r=e,i=r.attributes,a=r.segments,void 0===a&&(a=[{uri:i.baseUrl,timeline:i.periodIndex,resolvedUri:i.baseUrl||"",duration:i.sourceDuration,number:0}],i.duration=i.sourceDuration),{attributes:(n={NAME:i.id,BANDWIDTH:i.bandwidth},n["PROGRAM-ID"]=1,n),uri:"",endList:"static"===(i.type||"static"),timeline:i.periodIndex,resolvedUri:i.baseUrl||"",targetDuration:i.duration,segments:a,mediaSequence:a.length?a[0].number:1})],uri:""},t)},{})}(d)),l}(F(_(t),e).map(R))},t.parseUTCTiming=function(t){return function(t){var e=T(t,"UTCTiming")[0];if(!e)return null;var r=O(e);switch(r.schemeIdUri){case"urn:mpeg:dash:utc:http-head:2014":case"urn:mpeg:dash:utc:http-head:2012":r.method="HEAD";break;case"urn:mpeg:dash:utc:http-xsdate:2014":case"urn:mpeg:dash:utc:http-iso:2014":case"urn:mpeg:dash:utc:http-xsdate:2012":case"urn:mpeg:dash:utc:http-iso:2012":r.method="GET";break;case"urn:mpeg:dash:utc:direct:2014":case"urn:mpeg:dash:utc:direct:2012":r.method="DIRECT",r.value=Date.parse(r.value);break;case"urn:mpeg:dash:utc:http-ntp:2014":case"urn:mpeg:dash:utc:ntp:2014":case"urn:mpeg:dash:utc:sntp:2014":default:throw new Error(L)}return r}(_(t))},Object.defineProperty(t,"__esModule",{value:!0})}); | ||
/*! @name mpd-parser @version 0.8.0-0 @license Apache-2.0 */ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("global/window")):"function"==typeof define&&define.amd?define(["exports","global/window"],t):t(e.mpdParser={},e.window)}(this,function(e,t){"use strict";t=t&&t.hasOwnProperty("default")?t.default:t;var r=function(e){return!!e&&"object"==typeof e},n=function e(){for(var t=arguments.length,n=new Array(t),i=0;i<t;i++)n[i]=arguments[i];return n.reduce(function(t,n){return Object.keys(n).forEach(function(i){Array.isArray(t[i])&&Array.isArray(n[i])?t[i]=t[i].concat(n[i]):r(t[i])&&r(n[i])?t[i]=e(t[i],n[i]):t[i]=n[i]}),t},{})},i=function(e){return e.reduce(function(e,t){return e.concat(t)},[])},a=function(e){if(!e.length)return[];for(var t=[],r=0;r<e.length;r++)t.push(e[r]);return t},u="INVALID_NUMBER_OF_PERIOD",o="DASH_EMPTY_MANIFEST",s="DASH_INVALID_XML",d="NO_BASE_URL",c="SEGMENT_TIME_UNSPECIFIED",l="UNSUPPORTED_UTC_TIMING_SCHEME";"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var m,f=(function(e,t){var r,n,i,a,u;r=/^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/?#]*)?((?:[^\/\?#]*\/)*.*?)??(;.*?)?(\?.*?)?(#.*?)?$/,n=/^([^\/?#]*)(.*)$/,i=/(?:\/|^)\.(?=\/)/g,a=/(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g,u={buildAbsoluteURL:function(e,t,r){if(r=r||{},e=e.trim(),!(t=t.trim())){if(!r.alwaysNormalize)return e;var i=u.parseURL(e);if(!i)throw new Error("Error trying to parse base URL.");return i.path=u.normalizePath(i.path),u.buildURLFromParts(i)}var a=u.parseURL(t);if(!a)throw new Error("Error trying to parse relative URL.");if(a.scheme)return r.alwaysNormalize?(a.path=u.normalizePath(a.path),u.buildURLFromParts(a)):t;var o=u.parseURL(e);if(!o)throw new Error("Error trying to parse base URL.");if(!o.netLoc&&o.path&&"/"!==o.path[0]){var s=n.exec(o.path);o.netLoc=s[1],o.path=s[2]}o.netLoc&&!o.path&&(o.path="/");var d={scheme:o.scheme,netLoc:a.netLoc,path:null,params:a.params,query:a.query,fragment:a.fragment};if(!a.netLoc&&(d.netLoc=o.netLoc,"/"!==a.path[0]))if(a.path){var c=o.path,l=c.substring(0,c.lastIndexOf("/")+1)+a.path;d.path=u.normalizePath(l)}else d.path=o.path,a.params||(d.params=o.params,a.query||(d.query=o.query));return null===d.path&&(d.path=r.alwaysNormalize?u.normalizePath(a.path):a.path),u.buildURLFromParts(d)},parseURL:function(e){var t=r.exec(e);return t?{scheme:t[1]||"",netLoc:t[2]||"",path:t[3]||"",params:t[4]||"",query:t[5]||"",fragment:t[6]||""}:null},normalizePath:function(e){for(e=e.split("").reverse().join("").replace(i,"");e.length!==(e=e.replace(a,"")).length;);return e.split("").reverse().join("")},buildURLFromParts:function(e){return e.scheme+e.netLoc+e.path+e.params+e.query+e.fragment}},e.exports=u}(m={exports:{}},m.exports),m.exports),p=function(e,r){return/^[a-z]+:/i.test(r)?r:(/\/\//i.test(e)||(e=f.buildAbsoluteURL(t.location.href,e)),f.buildAbsoluteURL(e,r))},h=function(e){var t=e.baseUrl,r=void 0===t?"":t,n=e.source,i=void 0===n?"":n,a=e.range,u=void 0===a?"":a,o=e.indexRange,s=void 0===o?"":o,d={uri:i,resolvedUri:p(r||"",i)};if(u||s){var c=(u||s).split("-"),l=parseInt(c[0],10),m=parseInt(c[1],10);d.byterange={length:m-l+1,offset:l}}return d},v={static:function(e){var t=e.duration,r=e.timescale,n=void 0===r?1:r,i=e.sourceDuration;return{start:0,end:Math.ceil(i/(t/n))}},dynamic:function(e){var t=e.NOW,r=e.clientOffset,n=e.availabilityStartTime,i=e.timescale,a=void 0===i?1:i,u=e.duration,o=e.start,s=void 0===o?0:o,d=e.minimumUpdatePeriod,c=void 0===d?0:d,l=e.timeShiftBufferDepth,m=void 0===l?1/0:l,f=(t+r)/1e3,p=n+s,h=f+c-p,v=Math.ceil(h*a/u),g=Math.floor((f-p-m)*a/u),b=Math.floor((f-p)*a/u);return{start:Math.max(0,g),end:Math.min(v,b)}}},g=function(e){var t=e.type,r=void 0===t?"static":t,n=e.duration,i=e.timescale,a=void 0===i?1:i,u=e.sourceDuration,o=v[r](e),s=function(e,t){for(var r=[],n=e;n<t;n++)r.push(n);return r}(o.start,o.end).map(function(e){return function(t,r){var n=e.duration,i=e.timescale,a=void 0===i?1:i,u=e.periodIndex,o=e.startNumber;return{number:(void 0===o?1:o)+t,duration:n/a,timeline:u,time:r*n}}}(e));if("static"===r){var d=s.length-1;s[d].duration=u-n/a*d}return s},b=function(e){var t=e.baseUrl,r=e.initialization,n=void 0===r?{}:r,i=e.sourceDuration,a=e.timescale,u=void 0===a?1:a,o=e.indexRange,s=void 0===o?"":o,c=e.duration;if(!t)throw new Error(d);var l=h({baseUrl:t,source:n.sourceURL,range:n.range}),m=h({baseUrl:t,source:t,indexRange:s});if(m.map=l,c){var f=g(e);f.length&&(m.duration=f[0].duration,m.timeline=f[0].timeline)}else i&&(m.duration=i/u,m.timeline=0);return m.number=0,[m]},U=function(e,t,r){for(var n=e.sidx.map?e.sidx.map:null,i=e.sidx.duration,a=e.timeline||0,u=e.sidx.byterange,o=u.offset+u.length,s=t.timescale,d=t.references.filter(function(e){return 1!==e.referenceType}),c=[],l=o+t.firstOffset,m=0;m<d.length;m++){var f=t.references[m],p=f.referencedSize,h=f.subsegmentDuration,v=b({baseUrl:r,timescale:s,timeline:a,periodIndex:a,duration:h,sourceDuration:i,indexRange:l+"-"+(l+p-1)})[0];n&&(v.map=n),c.push(v),l+=p}return e.segments=c,e},y=function(e){var t;return(t=e.reduce(function(e,t){var r,n=t.attributes.id+(t.attributes.lang||"");e[n]?(t.segments[0].discontinuity=!0,(r=e[n].segments).push.apply(r,t.segments),t.attributes.contentProtection&&(e[n].attributes.contentProtection=t.attributes.contentProtection)):e[n]=t;return e},{}),Object.keys(t).map(function(e){return t[e]})).map(function(e){var t,r;return e.discontinuityStarts=(t=e.segments,r="discontinuity",t.reduce(function(e,t,n){return t[r]&&e.push(n),e},[])),e})},I=function(e,t){if(!Object.keys(t).length)return e;for(var r in e){var n=e[r],i=n.sidx.uri+"-"+(u=n.sidx.byterange,o=void 0,o=u.offset+u.length-1,u.offset+"-"+o),a=t[i]&&t[i].sidx;n.sidx&&a&&U(n,a,n.sidx.resolvedUri)}var u,o;return e},D=function(e){var t,r=e.attributes,n=e.segments,i=e.sidx,a={attributes:(t={NAME:r.id,AUDIO:"audio",SUBTITLES:"subs",RESOLUTION:{width:r.width,height:r.height},CODECS:r.codecs,BANDWIDTH:r.bandwidth},t["PROGRAM-ID"]=1,t),uri:"",endList:"static"===(r.type||"static"),timeline:r.periodIndex,resolvedUri:"",targetDuration:r.duration,segments:n,mediaSequence:n.length?n[0].number:1};return r.contentProtection&&(a.contentProtection=r.contentProtection),i&&(a.sidx=i),a},w=function(e,t){var r;if(void 0===t&&(t={}),!e.length)return{};var n=e[0].attributes,i=n.sourceDuration,a=n.minimumUpdatePeriod,u=void 0===a?0:a,o=y(e.filter(function(e){var t=e.attributes;return"video/mp4"===t.mimeType||"video"===t.contentType})).map(D),s=y(e.filter(function(e){var t=e.attributes;return"audio/mp4"===t.mimeType||"audio"===t.contentType})),d=e.filter(function(e){var t=e.attributes;return"text/vtt"===t.mimeType||"text"===t.contentType}),c={allowCache:!0,discontinuityStarts:[],segments:[],endList:!0,mediaGroups:(r={AUDIO:{},VIDEO:{}},r["CLOSED-CAPTIONS"]={},r.SUBTITLES={},r),uri:"",duration:i,playlists:I(o,t),minimumUpdatePeriod:1e3*u};return s.length&&(c.mediaGroups.AUDIO.audio=function(e,t){var r,n=e.reduce(function(e,n){var i=n.attributes.role&&n.attributes.role.value||"",a=n.attributes.lang||"",u="main";if(a){var o=i?" ("+i+")":"";u=""+n.attributes.lang+o}return e[u]&&e[u].playlists[0].attributes.BANDWIDTH>n.attributes.bandwidth?e:(e[u]={language:a,autoselect:!0,default:"main"===i,playlists:I([function(e){var t,r=e.attributes,n=e.segments,i=e.sidx,a={attributes:(t={NAME:r.id,BANDWIDTH:r.bandwidth,CODECS:r.codecs},t["PROGRAM-ID"]=1,t),uri:"",endList:"static"===(r.type||"static"),timeline:r.periodIndex,resolvedUri:"",targetDuration:r.duration,segments:n,mediaSequence:n.length?n[0].number:1};return r.contentProtection&&(a.contentProtection=r.contentProtection),i&&(a.sidx=i),a}(n)],t),uri:""},void 0===r&&"main"===i&&((r=n).default=!0),e)},{});r||(n[Object.keys(n)[0]].default=!0);return n}(s,t)),d.length&&(c.mediaGroups.SUBTITLES.subs=function(e,t){return e.reduce(function(e,r){var n,i,a,u,o=r.attributes.lang||"text";return e[o]?e:(e[o]={language:o,default:!1,autoselect:!1,playlists:I([(n=r,a=n.attributes,u=n.segments,void 0===u&&(u=[{uri:a.baseUrl,timeline:a.periodIndex,resolvedUri:a.baseUrl||"",duration:a.sourceDuration,number:0}],a.duration=a.sourceDuration),{attributes:(i={NAME:a.id,BANDWIDTH:a.bandwidth},i["PROGRAM-ID"]=1,i),uri:"",endList:"static"===(a.type||"static"),timeline:a.periodIndex,resolvedUri:a.baseUrl||"",targetDuration:a.duration,segments:u,mediaSequence:u.length?u[0].number:1})],t),uri:""},e)},{})}(d,t)),c},L=function(e,t,r){var n=e.NOW,i=e.clientOffset,a=e.availabilityStartTime,u=e.timescale,o=void 0===u?1:u,s=e.start,d=void 0===s?0:s,c=e.minimumUpdatePeriod,l=(n+i)/1e3+(void 0===c?0:c)-(a+d);return Math.ceil((l*o-t)/r)},x=function(e,t){for(var r=e.type,n=void 0===r?"static":r,i=e.minimumUpdatePeriod,a=void 0===i?0:i,u=e.media,o=void 0===u?"":u,s=e.sourceDuration,d=e.timescale,c=void 0===d?1:d,l=e.startNumber,m=void 0===l?1:l,f=e.periodIndex,p=[],h=-1,v=0;v<t.length;v++){var g=t[v],b=g.d,U=g.r||0,y=g.t||0;h<0&&(h=y),y&&y>h&&(h=y);var I=void 0;if(U<0){var D=v+1;I=D===t.length?"dynamic"===n&&a>0&&o.indexOf("$Number$")>0?L(e,h,b):(s*c-h)/b:(t[D].t-h)/b}else I=U+1;for(var w=m+p.length+I,x=m+p.length;x<w;)p.push({number:x,duration:b/c,time:h,timeline:f}),h+=b,x++}return p},R=/\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g,E=function(e,t){return e.replace(R,function(e){return function(t,r,n,i){if("$$"===t)return"$";if(void 0===e[r])return t;var a=""+e[r];return"RepresentationID"===r?a:(i=n?parseInt(i,10):1,a.length>=i?a:""+new Array(i-a.length+1).join("0")+a)}}(t))},P=function(e,t){var r={RepresentationID:e.id,Bandwidth:e.bandwidth||0},n=e.initialization,i=void 0===n?{sourceURL:"",range:""}:n,a=h({baseUrl:e.baseUrl,source:E(i.sourceURL,r),range:i.range});return function(e,t){return e.duration||t?e.duration?g(e):x(e,t):[{number:e.startNumber||1,duration:e.sourceDuration,time:0,timeline:e.periodIndex}]}(e,t).map(function(t){r.Number=t.number,r.Time=t.time;var n=E(e.media||"",r);return{uri:n,timeline:t.timeline,duration:t.duration,resolvedUri:p(e.baseUrl||"",n),map:a,number:t.number}})},T=function(e,t){var r=e.duration,n=e.segmentUrls,i=void 0===n?[]:n;if(!r&&!t||r&&t)throw new Error(c);var a,u=i.map(function(t){return function(e,t){var r=e.baseUrl,n=e.initialization,i=void 0===n?{}:n,a=h({baseUrl:r,source:i.sourceURL,range:i.range}),u=h({baseUrl:r,source:t.media,range:t.mediaRange});return u.map=a,u}(e,t)});return r&&(a=g(e)),t&&(a=x(e,t)),a.map(function(e,t){if(u[t]){var r=u[t];return r.timeline=e.timeline,r.duration=e.duration,r.number=e.number,r}}).filter(function(e){return e})},S=function(e){var t,r,i=e.attributes,a=e.segmentInfo;a.template?(r=P,t=n(i,a.template)):a.base?(r=b,t=n(i,a.base)):a.list&&(r=T,t=n(i,a.list));var u={attributes:i};if(!r)return u;var o=r(t,a.timeline);if(t.duration){var s=t,d=s.duration,c=s.timescale,l=void 0===c?1:c;t.duration=d/l}else o.length?t.duration=o.reduce(function(e,t){return Math.max(e,Math.ceil(t.duration))},0):t.duration=0;return u.attributes=t,u.segments=o,a.base&&t.indexRange&&(u.sidx=o[0],u.segments=[]),u},N=function(e,t){return a(e.childNodes).filter(function(e){return e.tagName===t})},O=function(e){return e.textContent.trim()},A=function(e){var t=/P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/.exec(e);if(!t)return 0;var r=t.slice(1),n=r[0],i=r[1],a=r[2],u=r[3],o=r[4],s=r[5];return 31536e3*parseFloat(n||0)+2592e3*parseFloat(i||0)+86400*parseFloat(a||0)+3600*parseFloat(u||0)+60*parseFloat(o||0)+parseFloat(s||0)},M={mediaPresentationDuration:function(e){return A(e)},availabilityStartTime:function(e){return/^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/.test(t=e)&&(t+="Z"),Date.parse(t)/1e3;var t},minimumUpdatePeriod:function(e){return A(e)},timeShiftBufferDepth:function(e){return A(e)},start:function(e){return A(e)},width:function(e){return parseInt(e,10)},height:function(e){return parseInt(e,10)},bandwidth:function(e){return parseInt(e,10)},startNumber:function(e){return parseInt(e,10)},timescale:function(e){return parseInt(e,10)},duration:function(e){var t=parseInt(e,10);return isNaN(t)?A(e):t},d:function(e){return parseInt(e,10)},t:function(e){return parseInt(e,10)},r:function(e){return parseInt(e,10)},DEFAULT:function(e){return e}},z=function(e){return e&&e.attributes?a(e.attributes).reduce(function(e,t){var r=M[t.name]||M.DEFAULT;return e[t.name]=r(t.value),e},{}):{}};var B={"urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b":"org.w3.clearkey","urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed":"com.widevine.alpha","urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":"com.microsoft.playready","urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb":"com.adobe.primetime"},C=function(e,t){return t.length?i(e.map(function(e){return t.map(function(t){return p(e,O(t))})})):e},F=function(e){var t=N(e,"SegmentTemplate")[0],r=N(e,"SegmentList")[0],i=r&&N(r,"SegmentURL").map(function(e){return n({tag:"SegmentURL"},z(e))}),a=N(e,"SegmentBase")[0],u=r||t,o=u&&N(u,"SegmentTimeline")[0],s=r||a||t,d=s&&N(s,"Initialization")[0],c=t&&z(t);c&&d?c.initialization=d&&z(d):c&&c.initialization&&(c.initialization={sourceURL:c.initialization});var l={template:c,timeline:o&&N(o,"S").map(function(e){return z(e)}),list:r&&n(z(r),{segmentUrls:i,initialization:z(d)}),base:a&&n(z(a),{initialization:z(d)})};return Object.keys(l).forEach(function(e){l[e]||delete l[e]}),l},_=function(e){return e.reduce(function(e,r){var n=z(r),i=B[n.schemeIdUri];if(i){e[i]={attributes:n};var a=N(r,"cenc:pssh")[0];if(a){var u=O(a),o=u&&function(e){for(var r=t.atob(e),n=new Uint8Array(r.length),i=0;i<r.length;i++)n[i]=r.charCodeAt(i);return n}(u);e[i].pssh=o}}return e},{})},j=function(e,t,r){return function(a){var u=z(a),o=C(t,N(a,"BaseURL")),s=N(a,"Role")[0],d={role:z(s)},c=n(e,u,d),l=_(N(a,"ContentProtection"));Object.keys(l).length&&(c=n(c,{contentProtection:l}));var m=F(a),f=N(a,"Representation"),p=n(r,m);return i(f.map(function(e,t,r){return function(i){var a=N(i,"BaseURL"),u=C(t,a),o=n(e,z(i)),s=F(i);return u.map(function(e){return{segmentInfo:n(r,s),attributes:n(o,{baseUrl:e})}})}}(c,o,p)))}},q=function(e,r){void 0===r&&(r={});var a=r,o=a.manifestUri,s=void 0===o?"":o,d=a.NOW,c=void 0===d?Date.now():d,l=a.clientOffset,m=void 0===l?0:l,f=N(e,"Period");if(!f.length)throw new Error(u);var p=z(e),h=C([s],N(e,"BaseURL"));return p.sourceDuration=p.mediaPresentationDuration||0,p.NOW=c,p.clientOffset=m,i(f.map(function(e,r){return function(a,u){var o=C(r,N(a,"BaseURL")),s=z(a),d=parseInt(s.id,10),c=t.isNaN(d)?u:d,l=n(e,{periodIndex:c}),m=N(a,"AdaptationSet"),f=F(a);return i(m.map(j(l,o,f)))}}(p,h)))},k=function(e){if(""===e)throw new Error(o);var r=(new t.DOMParser).parseFromString(e,"application/xml"),n=r&&"MPD"===r.documentElement.tagName?r.documentElement:null;if(!n||n&&n.getElementsByTagName("parsererror").length>0)throw new Error(s);return n};e.VERSION="0.8.0-0",e.parse=function(e,t){return void 0===t&&(t={}),w(q(k(e),t).map(S),t.sidxMapping)},e.parseUTCTiming=function(e){return function(e){var t=N(e,"UTCTiming")[0];if(!t)return null;var r=z(t);switch(r.schemeIdUri){case"urn:mpeg:dash:utc:http-head:2014":case"urn:mpeg:dash:utc:http-head:2012":r.method="HEAD";break;case"urn:mpeg:dash:utc:http-xsdate:2014":case"urn:mpeg:dash:utc:http-iso:2014":case"urn:mpeg:dash:utc:http-xsdate:2012":case"urn:mpeg:dash:utc:http-iso:2012":r.method="GET";break;case"urn:mpeg:dash:utc:direct:2014":case"urn:mpeg:dash:utc:direct:2012":r.method="DIRECT",r.value=Date.parse(r.value);break;case"urn:mpeg:dash:utc:http-ntp:2014":case"urn:mpeg:dash:utc:ntp:2014":case"urn:mpeg:dash:utc:sntp:2014":default:throw new Error(l)}return r}(k(e))},Object.defineProperty(e,"__esModule",{value:!0})}); |
{ | ||
"name": "mpd-parser", | ||
"version": "0.7.0", | ||
"version": "0.8.0-0", | ||
"description": "mpd parser", | ||
@@ -12,2 +12,4 @@ "main": "dist/mpd-parser.cjs.js", | ||
"scripts": { | ||
"prenetlify": "npm run build", | ||
"netlify": "node scripts/netlify.js", | ||
"prebuild": "npm run clean", | ||
@@ -65,13 +67,14 @@ "build": "npm-run-all -p build:*", | ||
"not-prerelease": "^1.0.1", | ||
"npm-run-all": "^4.1.3", | ||
"npm-merge-driver-install": "^1.0.0", | ||
"npm-run-all": "^4.1.5", | ||
"pkg-ok": "^2.2.0", | ||
"rollup": "^0.66.0", | ||
"rollup-plugin-string": "^2.0.2", | ||
"shelljs": "~0.8.2", | ||
"shx": "^0.3.2", | ||
"sinon": "^6.1.5", | ||
"videojs-generate-karma-config": "~3.0.0", | ||
"videojs-generate-rollup-config": "~2.2.0", | ||
"videojs-standard": "~7.1.0", | ||
"pkg-ok": "^2.2.0", | ||
"npm-merge-driver-install": "^1.0.0", | ||
"videojs-generator-verify": "~1.0.4" | ||
"videojs-generate-karma-config": "~5.0.1", | ||
"videojs-generate-rollup-config": "~2.3.0", | ||
"videojs-generator-verify": "~1.0.4", | ||
"videojs-standard": "~7.1.0" | ||
}, | ||
@@ -78,0 +81,0 @@ "generator-videojs-plugin": { |
@@ -10,4 +10,4 @@ import { version } from '../package.json'; | ||
export const parse = (manifestString, options) => | ||
toM3u8(toPlaylists(inheritAttributes(stringToMpdXml(manifestString), options))); | ||
export const parse = (manifestString, options = {}) => | ||
toM3u8(toPlaylists(inheritAttributes(stringToMpdXml(manifestString), options)), options.sidxMapping); | ||
@@ -14,0 +14,0 @@ /** |
@@ -35,4 +35,5 @@ import errors from '../errors'; | ||
}); | ||
const segment = urlTypeConverter({ baseUrl, source: baseUrl, range: indexRange }); | ||
const segment = urlTypeConverter({ baseUrl, source: baseUrl, indexRange }); | ||
segment.map = initSegment; | ||
@@ -59,1 +60,56 @@ | ||
}; | ||
export const addSegmentsToPlaylist = (playlist, sidx, baseUrl) => { | ||
// Retain init segment information | ||
const initSegment = playlist.sidx.map ? playlist.sidx.map : null; | ||
// Retain source duration from initial master manifest parsing | ||
const sourceDuration = playlist.sidx.duration; | ||
// Retain source timeline | ||
const timeline = playlist.timeline || 0; | ||
const sidxByteRange = playlist.sidx.byterange; | ||
const sidxEnd = sidxByteRange.offset + sidxByteRange.length; | ||
// Retain timescale of the parsed sidx | ||
const timescale = sidx.timescale; | ||
// referenceType 1 refers to other sidx boxes | ||
const mediaReferences = sidx.references.filter(r => r.referenceType !== 1); | ||
const segments = []; | ||
// firstOffset is the offset from the end of the sidx box | ||
let startIndex = sidxEnd + sidx.firstOffset; | ||
for (let i = 0; i < mediaReferences.length; i++) { | ||
const reference = sidx.references[i]; | ||
// size of the referenced (sub)segment | ||
const size = reference.referencedSize; | ||
// duration of the referenced (sub)segment, in the timescale | ||
// this will be converted to seconds when generating segments | ||
const duration = reference.subsegmentDuration; | ||
// should be an inclusive range | ||
const endIndex = startIndex + size - 1; | ||
const indexRange = `${startIndex}-${endIndex}`; | ||
const attributes = { | ||
baseUrl, | ||
timescale, | ||
timeline, | ||
// this is used in parseByDuration | ||
periodIndex: timeline, | ||
duration, | ||
sourceDuration, | ||
indexRange | ||
}; | ||
const segment = segmentsFromBase(attributes)[0]; | ||
if (initSegment) { | ||
segment.map = initSegment; | ||
} | ||
segments.push(segment); | ||
startIndex += size; | ||
} | ||
playlist.segments = segments; | ||
return playlist; | ||
}; |
@@ -23,8 +23,9 @@ import resolveUrl from '../utils/resolveUrl'; | ||
* @param {string} source - source url for segment | ||
* @param {string} range - optional range used for range calls, follows | ||
* @param {string} range - optional range used for range calls, | ||
* follows RFC 2616, Clause 14.35.1 | ||
* @return {SingleUri} full segment information transformed into a format similar | ||
* to m3u8-parser | ||
*/ | ||
export const urlTypeToSegment = ({ baseUrl = '', source = '', range = '' }) => { | ||
const init = { | ||
export const urlTypeToSegment = ({ baseUrl = '', source = '', range = '', indexRange = '' }) => { | ||
const segment = { | ||
uri: source, | ||
@@ -34,9 +35,12 @@ resolvedUri: resolveUrl(baseUrl || '', source) | ||
if (range) { | ||
const ranges = range.split('-'); | ||
if (range || indexRange) { | ||
const rangeStr = range ? range : indexRange; | ||
const ranges = rangeStr.split('-'); | ||
const startRange = parseInt(ranges[0], 10); | ||
const endRange = parseInt(ranges[1], 10); | ||
init.byterange = { | ||
length: endRange - startRange, | ||
// byterange should be inclusive according to | ||
// RFC 2616, Clause 14.35.1 | ||
segment.byterange = { | ||
length: endRange - startRange + 1, | ||
offset: startRange | ||
@@ -46,5 +50,13 @@ }; | ||
return init; | ||
return segment; | ||
}; | ||
export const byteRangeToString = (byterange) => { | ||
// `endRange` is one less than `offset + length` because the HTTP range | ||
// header uses inclusive ranges | ||
const endRange = byterange.offset + byterange.length - 1; | ||
return `${byterange.offset}-${endRange}`; | ||
}; | ||
export default urlTypeToSegment; |
import { values } from './utils/object'; | ||
import { findIndexes } from './utils/list'; | ||
import { addSegmentsToPlaylist } from './segment/segmentBase'; | ||
import { byteRangeToString } from './segment/urlType'; | ||
@@ -39,3 +41,22 @@ const mergeDiscontiguousPlaylists = playlists => { | ||
export const formatAudioPlaylist = ({ attributes, segments }) => { | ||
const addSegmentInfoFromSidx = (playlists, sidxMapping) => { | ||
if (!Object.keys(sidxMapping).length) { | ||
return playlists; | ||
} | ||
for (const i in playlists) { | ||
const playlist = playlists[i]; | ||
const sidxKey = playlist.sidx.uri + '-' + | ||
byteRangeToString(playlist.sidx.byterange); | ||
const sidxMatch = sidxMapping[sidxKey] && sidxMapping[sidxKey].sidx; | ||
if (playlist.sidx && sidxMatch) { | ||
addSegmentsToPlaylist(playlist, sidxMatch, playlist.sidx.resolvedUri); | ||
} | ||
} | ||
return playlists; | ||
}; | ||
export const formatAudioPlaylist = ({ attributes, segments, sidx }) => { | ||
const playlist = { | ||
@@ -61,2 +82,6 @@ attributes: { | ||
if (sidx) { | ||
playlist.sidx = sidx; | ||
} | ||
return playlist; | ||
@@ -94,6 +119,8 @@ }; | ||
export const organizeAudioPlaylists = playlists => { | ||
return playlists.reduce((a, playlist) => { | ||
export const organizeAudioPlaylists = (playlists, sidxMapping) => { | ||
let mainPlaylist; | ||
const formattedPlaylists = playlists.reduce((a, playlist) => { | ||
const role = playlist.attributes.role && | ||
playlist.attributes.role.value || 'main'; | ||
playlist.attributes.role.value || ''; | ||
const language = playlist.attributes.lang || ''; | ||
@@ -104,3 +131,5 @@ | ||
if (language) { | ||
label = `${playlist.attributes.lang} (${role})`; | ||
const roleLabel = role ? ` (${role})` : ''; | ||
label = `${playlist.attributes.lang}${roleLabel}`; | ||
} | ||
@@ -119,11 +148,28 @@ | ||
default: role === 'main', | ||
playlists: [formatAudioPlaylist(playlist)], | ||
playlists: addSegmentInfoFromSidx( | ||
[formatAudioPlaylist(playlist)], | ||
sidxMapping | ||
), | ||
uri: '' | ||
}; | ||
if (typeof mainPlaylist === 'undefined' && role === 'main') { | ||
mainPlaylist = playlist; | ||
mainPlaylist.default = true; | ||
} | ||
return a; | ||
}, {}); | ||
// if no playlists have role "main", mark the first as main | ||
if (!mainPlaylist) { | ||
const firstLabel = Object.keys(formattedPlaylists)[0]; | ||
formattedPlaylists[firstLabel].default = true; | ||
} | ||
return formattedPlaylists; | ||
}; | ||
export const organizeVttPlaylists = playlists => { | ||
export const organizeVttPlaylists = (playlists, sidxMapping) => { | ||
return playlists.reduce((a, playlist) => { | ||
@@ -141,3 +187,6 @@ const label = playlist.attributes.lang || 'text'; | ||
autoselect: false, | ||
playlists: [formatVttPlaylist(playlist)], | ||
playlists: addSegmentInfoFromSidx( | ||
[formatVttPlaylist(playlist)], | ||
sidxMapping | ||
), | ||
uri: '' | ||
@@ -150,3 +199,3 @@ }; | ||
export const formatVideoPlaylist = ({ attributes, segments }) => { | ||
export const formatVideoPlaylist = ({ attributes, segments, sidx }) => { | ||
const playlist = { | ||
@@ -178,6 +227,10 @@ attributes: { | ||
if (sidx) { | ||
playlist.sidx = sidx; | ||
} | ||
return playlist; | ||
}; | ||
export const toM3u8 = dashPlaylists => { | ||
export const toM3u8 = (dashPlaylists, sidxMapping = {}) => { | ||
if (!dashPlaylists.length) { | ||
@@ -219,3 +272,3 @@ return {}; | ||
duration, | ||
playlists: videoPlaylists, | ||
playlists: addSegmentInfoFromSidx(videoPlaylists, sidxMapping), | ||
minimumUpdatePeriod: minimumUpdatePeriod * 1000 | ||
@@ -225,7 +278,7 @@ }; | ||
if (audioPlaylists.length) { | ||
master.mediaGroups.AUDIO.audio = organizeAudioPlaylists(audioPlaylists); | ||
master.mediaGroups.AUDIO.audio = organizeAudioPlaylists(audioPlaylists, sidxMapping); | ||
} | ||
if (vttPlaylists.length) { | ||
master.mediaGroups.SUBTITLES.subs = organizeVttPlaylists(vttPlaylists); | ||
master.mediaGroups.SUBTITLES.subs = organizeVttPlaylists(vttPlaylists, sidxMapping); | ||
} | ||
@@ -232,0 +285,0 @@ |
import { merge } from './utils/object'; | ||
import { segmentsFromTemplate } from './segment/segmentTemplate'; | ||
import { segmentsFromList } from './segment/segmentList'; | ||
import { segmentsFromBase } from './segment/segmentBase'; | ||
import { | ||
segmentsFromBase | ||
} from './segment/segmentBase'; | ||
@@ -21,4 +23,8 @@ export const generateSegments = ({ attributes, segmentInfo }) => { | ||
const segmentsInfo = { | ||
attributes | ||
}; | ||
if (!segmentsFn) { | ||
return { attributes }; | ||
return segmentsInfo; | ||
} | ||
@@ -45,8 +51,14 @@ | ||
return { | ||
attributes: segmentAttributes, | ||
segments | ||
}; | ||
segmentsInfo.attributes = segmentAttributes; | ||
segmentsInfo.segments = segments; | ||
// This is a sidx box without actual segment information | ||
if (segmentInfo.base && segmentAttributes.indexRange) { | ||
segmentsInfo.sidx = segments[0]; | ||
segmentsInfo.segments = []; | ||
} | ||
return segmentsInfo; | ||
}; | ||
export const toPlaylists = (representations) => representations.map(generateSegments); |
@@ -79,5 +79,5 @@ export const parsedManifest = { | ||
}, | ||
['es (main)']: { | ||
['es']: { | ||
autoselect: true, | ||
default: true, | ||
default: false, | ||
language: 'es', | ||
@@ -84,0 +84,0 @@ playlists: [{ |
import QUnit from 'qunit'; | ||
import { | ||
segmentsFromBase | ||
segmentsFromBase, | ||
addSegmentsToPlaylist | ||
} from '../../src/segment/segmentBase'; | ||
@@ -132,3 +133,3 @@ import errors from '../../src/errors'; | ||
byterange: { | ||
length: 4, | ||
length: 5, | ||
offset: 121 | ||
@@ -146,1 +147,50 @@ } | ||
}); | ||
QUnit.module('segmentBase - addSegmentsToPlaylist'); | ||
QUnit.test('generates playlist from sidx references', function(assert) { | ||
const baseUrl = 'http://www.example.com/i.fmp4'; | ||
const playlist = { | ||
sidx: { | ||
map: { | ||
byterange: { | ||
offset: 0, | ||
length: 10 | ||
} | ||
}, | ||
duration: 10, | ||
byterange: { | ||
offset: 9, | ||
length: 11 | ||
} | ||
}, | ||
segments: [] | ||
}; | ||
const sidx = { | ||
timescale: 1, | ||
firstOffset: 0, | ||
references: [{ | ||
referenceType: 0, | ||
referencedSize: 5, | ||
subsegmentDuration: 2 | ||
}] | ||
}; | ||
assert.deepEqual(addSegmentsToPlaylist(playlist, sidx, baseUrl).segments, [{ | ||
map: { | ||
byterange: { | ||
offset: 0, | ||
length: 10 | ||
} | ||
}, | ||
uri: 'http://www.example.com/i.fmp4', | ||
resolvedUri: 'http://www.example.com/i.fmp4', | ||
byterange: { | ||
offset: 20, | ||
length: 5 | ||
}, | ||
duration: 2, | ||
timeline: 0, | ||
number: 0 | ||
}]); | ||
}); |
@@ -428,3 +428,3 @@ import QUnit from 'qunit'; | ||
byterange: { | ||
length: 200, | ||
length: 201, | ||
offset: 0 | ||
@@ -439,3 +439,3 @@ }, | ||
byterange: { | ||
length: 199, | ||
length: 200, | ||
offset: 201 | ||
@@ -522,3 +522,3 @@ }, | ||
byterange: { | ||
length: 4, | ||
length: 5, | ||
offset: 121 | ||
@@ -537,3 +537,3 @@ } | ||
byterange: { | ||
length: 4, | ||
length: 5, | ||
offset: 121 | ||
@@ -540,0 +540,0 @@ } |
@@ -1315,3 +1315,3 @@ import QUnit from 'qunit'; | ||
byterange: { | ||
length: 4, | ||
length: 5, | ||
offset: 121 | ||
@@ -1331,3 +1331,3 @@ } | ||
byterange: { | ||
length: 4, | ||
length: 5, | ||
offset: 121 | ||
@@ -1347,3 +1347,3 @@ } | ||
byterange: { | ||
length: 4, | ||
length: 5, | ||
offset: 121 | ||
@@ -1350,0 +1350,0 @@ } |
import QUnit from 'qunit'; | ||
import urlTypeConverter from '../../src/segment/urlType'; | ||
import { | ||
urlTypeToSegment as urlTypeConverter, | ||
byteRangeToString | ||
} from '../../src/segment/urlType'; | ||
@@ -33,3 +36,3 @@ QUnit.module('urlType - urlTypeConverter'); | ||
offset: 101, | ||
length: 4 | ||
length: 5 | ||
} | ||
@@ -39,2 +42,17 @@ }); | ||
QUnit.test('returns correct object if given baseUrl, source and indexRange', function(assert) { | ||
assert.deepEqual(urlTypeConverter({ | ||
baseUrl: 'http://example.com', | ||
source: 'sidx.fmp4', | ||
indexRange: '101-105' | ||
}), { | ||
resolvedUri: 'http://example.com/sidx.fmp4', | ||
uri: 'sidx.fmp4', | ||
byterange: { | ||
offset: 101, | ||
length: 5 | ||
} | ||
}); | ||
}); | ||
QUnit.test('returns correct object if given baseUrl and range', function(assert) { | ||
@@ -49,5 +67,29 @@ assert.deepEqual(urlTypeConverter({ | ||
offset: 101, | ||
length: 4 | ||
length: 5 | ||
} | ||
}); | ||
}); | ||
QUnit.test('returns correct object if given baseUrl and indexRange', function(assert) { | ||
assert.deepEqual(urlTypeConverter({ | ||
baseUrl: 'http://example.com', | ||
indexRange: '101-105' | ||
}), { | ||
resolvedUri: 'http://example.com', | ||
uri: '', | ||
byterange: { | ||
offset: 101, | ||
length: 5 | ||
} | ||
}); | ||
}); | ||
QUnit.module('urlType - byteRangeToString'); | ||
QUnit.test('returns correct string representing byterange object', function(assert) { | ||
assert.strictEqual(byteRangeToString({ | ||
offset: 0, | ||
length: 100 | ||
}), | ||
'0-99'); | ||
}); |
@@ -462,4 +462,92 @@ import { toM3u8 } from '../src/toM3u8'; | ||
QUnit.test('playlists with sidx and sidxMapping', function(assert) { | ||
const input = [{ | ||
attributes: { | ||
sourceDuration: 100, | ||
id: '1', | ||
width: 800, | ||
height: 600, | ||
codecs: 'foo;bar', | ||
duration: 0, | ||
bandwidth: 10000, | ||
periodIndex: 1, | ||
mimeType: 'video/mp4' | ||
}, | ||
segments: [], | ||
sidx: { | ||
byterange: { | ||
offset: 10, | ||
length: 10 | ||
}, | ||
uri: 'sidx.mp4', | ||
resolvedUri: 'http://example.com/sidx.mp4', | ||
duration: 10 | ||
}, | ||
uri: 'http://example.com/fmp4.mp4' | ||
}]; | ||
const mapping = { | ||
'sidx.mp4-10-19': { | ||
sidx: { | ||
timescale: 1, | ||
firstOffset: 0, | ||
references: [{ | ||
referenceType: 0, | ||
referencedSize: 5, | ||
subsegmentDuration: 2 | ||
}] | ||
} | ||
} | ||
}; | ||
const expected = [{ | ||
attributes: { | ||
AUDIO: 'audio', | ||
SUBTITLES: 'subs', | ||
BANDWIDTH: 10000, | ||
CODECS: 'foo;bar', | ||
NAME: '1', | ||
['PROGRAM-ID']: 1, | ||
RESOLUTION: { | ||
height: 600, | ||
width: 800 | ||
} | ||
}, | ||
sidx: { | ||
byterange: { | ||
offset: 10, | ||
length: 10 | ||
}, | ||
uri: 'sidx.mp4', | ||
resolvedUri: 'http://example.com/sidx.mp4', | ||
duration: 10 | ||
}, | ||
targetDuration: 0, | ||
timeline: 1, | ||
uri: '', | ||
segments: [{ | ||
map: { | ||
resolvedUri: 'http://example.com/sidx.mp4', | ||
uri: '' | ||
}, | ||
byterange: { | ||
offset: 20, | ||
length: 5 | ||
}, | ||
uri: 'http://example.com/sidx.mp4', | ||
resolvedUri: 'http://example.com/sidx.mp4', | ||
duration: 2, | ||
number: 0, | ||
timeline: 1 | ||
}], | ||
endList: true, | ||
mediaSequence: 1, | ||
resolvedUri: '' | ||
}]; | ||
assert.deepEqual(toM3u8(input, mapping).playlists, expected); | ||
}); | ||
QUnit.test('no playlists', function(assert) { | ||
assert.deepEqual(toM3u8([]), {}); | ||
}); |
@@ -74,2 +74,44 @@ import { | ||
QUnit.test('segment base with sidx', function(assert) { | ||
const representations = [{ | ||
attributes: { | ||
baseUrl: 'http://example.com/', | ||
periodIndex: 0, | ||
sourceDuration: 2, | ||
indexRange: '10-19' | ||
}, | ||
segmentInfo: { | ||
base: true | ||
} | ||
}]; | ||
const playlists = [{ | ||
attributes: { | ||
baseUrl: 'http://example.com/', | ||
periodIndex: 0, | ||
sourceDuration: 2, | ||
duration: 2, | ||
indexRange: '10-19' | ||
}, | ||
segments: [], | ||
sidx: { | ||
map: { | ||
resolvedUri: 'http://example.com/', | ||
uri: '' | ||
}, | ||
resolvedUri: 'http://example.com/', | ||
uri: 'http://example.com/', | ||
byterange: { | ||
offset: 10, | ||
length: 10 | ||
}, | ||
timeline: 0, | ||
duration: 2, | ||
number: 0 | ||
} | ||
}]; | ||
assert.deepEqual(toPlaylists(representations), playlists); | ||
}); | ||
QUnit.test('segment list', function(assert) { | ||
@@ -76,0 +118,0 @@ const representations = [{ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
995822
33982
1
20