dasha 3.1.1 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dasha.js CHANGED
@@ -1,6 +1,1514 @@
1
- "use strict";var R=(e,r)=>()=>(r||e((r={exports:{}}).exports,r),r.exports);var ee=R((Tr,Z)=>{"use strict";function we(e,r={}){var t=r.pos||0,s=!!r.keepComments,n=!!r.keepWhitespace,i="<",o=60,a=">",c=62,l=45,h=47,d=33,u=39,p=34,C=91,S=93;function v(g){for(var f=[];e[t];)if(e.charCodeAt(t)==o){if(e.charCodeAt(t+1)===h){var A=t+2;t=e.indexOf(a,t);var B=e.substring(A,t);if(B.indexOf(g)==-1){let b=e.substring(0,t).split(`
2
- `);throw new Error(`Unexpected close tag
3
- Line: `+(b.length-1)+`
4
- Column: `+(b[b.length-1].length+1)+`
5
- Char: `+e[t])}return t+1&&(t+=1),f}else if(e.charCodeAt(t+1)===d){if(e.charCodeAt(t+2)==l){let b=t;for(;t!==-1&&!(e.charCodeAt(t)===c&&e.charCodeAt(t-1)==l&&e.charCodeAt(t-2)==l&&t!=-1);)t=e.indexOf(a,t+1);t===-1&&(t=e.length),s&&f.push(e.substring(b,t+1))}else if(e.charCodeAt(t+2)===C&&e.charCodeAt(t+8)===C&&e.substr(t+3,5).toLowerCase()==="cdata"){var I=e.indexOf("]]>",t);I==-1?(f.push(e.substr(t+9)),t=e.length):(f.push(e.substring(t+9,I)),t=I+3);continue}else{let b=t+1;t+=2;for(var m=!1;(e.charCodeAt(t)!==c||m===!0)&&e[t];)e.charCodeAt(t)===C?m=!0:m===!0&&e.charCodeAt(t)===S&&(m=!1),t++;f.push(e.substring(b,t))}t++;continue}var N=L();f.push(N),N.tagName[0]==="?"&&(f.push(...N.children),N.children=[])}else{let b=O();if(n)b.length>0&&f.push(b);else{var _=b.trim();_.length>0&&f.push(_)}t++}return f}function O(){var g=t;return t=e.indexOf(i,t)-1,t===-2&&(t=e.length),e.slice(g,t+1)}var U=`\r
6
- >/= `;function V(){for(var g=t;U.indexOf(e[t])===-1&&e[t];)t++;return e.slice(g,t)}var G=r.noChildNodes||["img","br","input","meta","link","hr"];function L(){t++;let g=V(),f={},A=[];for(;e.charCodeAt(t)!==c&&e[t];){var B=e.charCodeAt(t);if(B>64&&B<91||B>96&&B<123){for(var I=V(),m=e.charCodeAt(t);m&&m!==u&&m!==p&&!(m>64&&m<91||m>96&&m<123)&&m!==c;)t++,m=e.charCodeAt(t);if(m===u||m===p){var N=T();if(t===-1)return{tagName:g,attributes:f,children:A}}else N=null,t--;f[I]=N}t++}if(e.charCodeAt(t-1)!==h)if(g=="script"){let _=t+1;t=e.indexOf("</script>",t),A=[e.slice(_,t)],t+=9}else if(g=="style"){let _=t+1;t=e.indexOf("</style>",t),A=[e.slice(_,t)],t+=8}else G.indexOf(g)===-1?(t++,A=v(g)):t++;else t++;return{tagName:g,attributes:f,children:A}}function T(){var g=e[t],f=t+1;return t=e.indexOf(g,f),e.slice(f,t)}function $(){var g=new RegExp("\\s"+r.attrName+`\\s*=['"]`+r.attrValue+`['"]`).exec(e);return g?g.index:-1}let y=null;if(r.attrValue!==void 0)for(r.attrName=r.attrName||"id",y=[];(t=$())!==-1;)t=e.lastIndexOf("<",t),t!==-1&&y.push(L()),e=e.substr(t),t=0;else r.parseNode?y=L():y=v("");return r.filter&&(y=H(y,r.filter)),r.setPos&&(y.pos=t),y}function H(e,r,t=0,s=""){var n=[];return e.forEach(function(i,o){if(typeof i=="object"&&r(i,o,t,s)&&n.push(i),i.children){var a=H(i.children,r,t+1,(s?s+".":"")+o+"."+i.tagName);n=n.concat(a)}}),n}Z.exports={parse:we,filter:H}});var D=R((yr,ne)=>{"use strict";var te=(e,r=["Bytes","KB","MB","GB","TB"])=>{if(e==0)return`0 ${r[0]}`;let t=parseInt(Math.floor(Math.log(e)/Math.log(1024)));return t==0?e+" "+r[t]:(e/Math.pow(1024,t)).toFixed(1)+" "+r[t]},Te=(e,r)=>({b:e*r,kb:e/1e3*r,mb:e/8e6*r,gb:e/8e9*r,toString(){return te(e*r)}}),ye=e=>({bps:e,kbps:e/1e3,mbps:e/8e6,gbps:e/8e9,toString(){return te(e,["bps","Kbps","Mbps","Gbps"])}}),re=[{width:7680,height:4320},{width:3840,height:2160},{width:2560,height:1440},{width:1920,height:1080},{width:1280,height:720},{width:1024,height:576},{width:854,height:480},{width:640,height:360},{width:426,height:240},{width:256,height:144}],Ne=e=>re.find(r=>r.height===e)?.width,se=e=>re.find(r=>r.width===e)?.height,Be=e=>`${se(e.width)||e.height}p`,Ue=e=>{let r=Math.max(...e.map(t=>t.bitrate.bps));return e.find(t=>t.bitrate.bps===r)},_e=e=>{let a=/P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/.exec(e);if(!a)return 0;let[c,l,h,d,u,p]=a.slice(1);return parseFloat(c||0)*31536e3+parseFloat(l||0)*2592e3+parseFloat(h||0)*86400+parseFloat(d||0)*3600+parseFloat(u||0)*60+parseFloat(p||0)},Re=e=>{try{return Intl.getCanonicalLocales(e),!0}catch{return}};ne.exports={parseSize:Te,parseBitrate:ye,getWidth:Ne,getHeight:se,getQualityLabel:Be,getBestTrack:Ue,parseDuration:_e,isLanguageTagValid:Re}});var Y=R((Nr,ie)=>{"use strict";var{parseBitrate:Ee,getQualityLabel:Le,parseSize:Ie}=D(),F={avc:"H.264",hevc:"H.265",vc1:"VC-1",vp8:"VP8",vp9:"VP9",av1:"AV1"},P={sdr:"SDR",hlg:"HLG",hdr10:"HDR10",hdr10p:"HDR10+",dv:"DV"},Q={Unspecified:0,BT_709:1,BT_601_625:5,BT_601_525:6,BT_2020_and_2100:9,SMPTE_ST_2113_and_EG_4321:12},q={Unspecified:0,BT_709:1,BT_601:6,BT_2020:14,BT_2100:15,BT_2100_PQ:16,BT_2100_HLG:18},De={RGB:0,YCbCr_BT_709:1,YCbCr_BT_601_625:5,YCbCr_BT_601_525:6,YCbCr_BT_2020_and_2100:9,ICtCp_BT_2100:14},Fe=e=>{let r=e.toLowerCase().trim().split(".")[0],t=["avc1","avc2","avc3","dva1","dvav"],s=["hev1","hev2","hev3","hvc1","hvc2","hvc3","dvh1","dvhe","lhv1","lhe1"],n=["vc-1"],i=["vp08","vp8"],o=["vp09","vp9"],a=["av01"];if(t.includes(r))return F.avc;if(s.includes(r)||n.includes(r))return F.hevc;if(i.includes(r))return F.vp8;if(o.includes(r))return F.vp9;if(a.includes(r))return F.av1;throw new Error(`The MIME ${e} is not supported as video codec`)},Me=(e,r,t)=>(r==5&&(r=q.BT_601),e==Q.Unspecified&&r==q.Unspecified&&t==De.RGB||[Q.BT_601_625,Q.BT_601_525].includes(e)?P.sdr:q.BT_2100_PQ===r?P.hdr10:q.BT_2100_HLG===r?P.hlg:P.sdr),Oe=({id:e,label:r,type:t,codec:s,dynamicRange:n,contentProtection:i,bitrate:o,duration:a,width:c,height:l,fps:h,language:d,segments:u})=>{let p=Ee(Number(o)),C=Number(c),S=Number(l),v=a?Ie(Number(o),Number(a)):void 0;return{id:e,label:r,type:t,codec:s,bitrate:p,size:v,protection:i,segments:u,dynamicRange:n,language:d,width:C,height:S,fps:Number(h),quality:Le({width:C,height:S}),toString(){return["VIDEO",`[${s}, ${n}]`,d,`${c}x${l} @ ${p.kbps} kb/s, ${h} FPS`].join(" | ")}}},Pe=e=>{for(let r of e.toLowerCase().split(",")){let t=r.trim().split(".")[0];try{return Fe(t)}catch{continue}}throw new Error(`No MIME types matched any supported Video Codecs in ${e}`)},ke=(e,r=[],t=[])=>{if(["dva1","dvav","dvhe","dvh1"].some(u=>e.startsWith(u)))return P.dv;let n="urn:mpeg:mpegB:cicp:ColourPrimaries",i="urn:mpeg:mpegB:cicp:TransferCharacteristics",o="urn:mpeg:mpegB:cicp:MatrixCoefficients",a=[...t,...r],c=u=>a.filter(p=>p.attributes.schemeIdUri===u).map(p=>parseInt(p.attributes.value)),l=c(n).reduce((u,p)=>u+p,0),h=c(i).reduce((u,p)=>u+p,0),d=c(o).reduce((u,p)=>u+p,0);return Me(l,h,d)};ie.exports={parseVideoCodec:Pe,parseDynamicRange:ke,createVideoTrack:Oe,VIDEO_CODECS:F}});var k=R((Br,de)=>{"use strict";var{getBestTrack:oe}=D(),Ve=e=>e.toLowerCase().split(",").map(r=>r.trim().split(".")[0]),ae=e=>({width:r,height:t})=>e.filter(s=>(!r||s.width===r)&&(!t||s.height===t)),z=e=>r=>{if(!r?.length)return e;let t=e.filter(s=>r.includes(s.codec));return t.sort((s,n)=>n.bitrate.bps-s.bitrate.bps),t},$e=e=>z(e),ce=e=>r=>{if(!r)return[oe(e)];let t=String(r).includes("p")?r:`${r}p`,s=e.filter(n=>n.quality===t);return s.sort((n,i)=>i.bitrate.bps-n.bitrate.bps),s.length?s:[oe(e)]},Ge=e=>z(e),ue=e=>(r=[],t)=>{if(!r.length){let o=e.filter(a=>a.language);if(o.length)for(let a of o)r.includes(a.language)||r.push(a.language);else return e.sort((a,c)=>c.bitrate.bps-a.bitrate.bps),e.slice(0,t)}let s=[];for(let o of r){let a=e.filter(c=>c.language?.startsWith(o));s.push(...a)}let n=[],i=[...new Set(s.map(o=>o.language))];for(let o of i){let a=s.filter(c=>c.language===o).slice(0,t);n.push(...a)}return n},le=e=>r=>{if(!r)return e;let t=typeof r=="string"?parseFloat(r):r;return e.filter(s=>s.channels===t)},qe=e=>r=>r.length?e.filter(t=>r.some(s=>t.language?.startsWith(s)||t.label?.startsWith(s))):e,We=(e,r)=>ae(e)(r),He=(e,r)=>ce(e)(r),Qe=(e,r)=>z(e)(r),Ye=(e,r,t)=>ue(e)(r,t),ze=(e,r)=>le(e)(r);de.exports={parseMimes:Ve,createResolutionFilter:ae,createVideoCodecFilter:$e,createVideoQualityFilter:ce,createAudioCodecFilter:Ge,createAudioLanguageFilter:ue,createAudioChannelsFilter:le,createSubtitleLanguageFilter:qe,filterByResolution:We,filterByQuality:He,filterByCodecs:Qe,filterByLanguages:Ye,filterByChannels:ze}});var j=R((Ur,pe)=>{"use strict";var{parseMimes:je}=k(),{parseBitrate:Ke,parseSize:Xe}=D(),E={AAC:"AAC",AC3:"DD",EC3:"DD+",OPUS:"OPUS",OGG:"VORB",DTS:"DTS",ALAC:"ALAC",FLAC:"FLAC"},Je=e=>{switch(e.toLowerCase().trim().split(".")[0]){case"mp4a":return E.AAC;case"ac-3":return E.AC3;case"ec-3":return E.EC3;case"opus":return E.OPUS;case"dtsc":return E.DTS;case"alac":return E.ALAC;case"flac":return E.FLAC;default:throw new Error(`The MIME ${e} is not supported as audio codec`)}},xe=e=>{let r=je(e);for(let t of r)try{return Je(t)}catch{continue}throw new Error(`No MIME types matched any supported Audio Codecs in ${e}`)},Ze=(e=[])=>{let r="tag:dolby.com,2018:dash:EC3_ExtensionComplexityIndex:2018";for(let t of e)if(t.attributes.schemeIdUri===r)return parseInt(t.attributes.value)},et=(e=[])=>{for(let r of e){let{schemeIdUri:t,value:s}=r.attributes,n=t=="urn:mpeg:dash:role:2011"&&s==="descriptive",i=t=="urn:tva:metadata:cs:AudioPurposeCS:2007"&&s==="1";if(n||i)return!0}return!1},tt=e=>{let r=t=>t>="0"&&t<="9";if(typeof e=="string"){if(e.toUpperCase()=="A000")return 2;if(e.toUpperCase()=="F801")return 5.1;if(r(e.replace("ch","").replace(".","")[0]))return parseFloat(e.replace("ch",""));throw new Error(`Unsupported audio channels value, '${e}'`)}return parseFloat(e)},rt=({id:e,label:r,type:t,codec:s,channels:n,bitrate:i,duration:o,jointObjectCoding:a=0,isDescriptive:c=!1,language:l,segments:h})=>{let d=Ke(Number(i)),u=tt(n),p=o?Xe(Number(i),Number(o)):void 0;return{id:e,label:r,type:t,codec:s,bitrate:d,size:p,language:l,segments:h,channels:u,jointObjectCoding:a,isDescriptive:c,toString(){return["AUDIO",`[${s}]`,`${u||"?"}`+(a?` (JOC ${a})`:""),`${d.kbps} kb/s`,l].join(" | ")}}};pe.exports={AUDIO_CODECS:E,parseAudioCodec:xe,createAudioTrack:rt,getDolbyDigitalPlusComplexityIndex:Ze,checkIsDescriptive:et}});var ge=R((_r,he)=>{"use strict";var{parseMimes:st}=k(),{parseBitrate:nt,parseSize:it}=D(),M={SubRip:"SRT",SubStationAlpha:"SSA",SubStationAlphav4:"ASS",TimedTextMarkupLang:"TTML",WebVTT:"VTT",fTTML:"STPP",fVTT:"WVTT"},ot=e=>{switch(e.toLowerCase().trim().split(".")[0]){case"srt":case"x-subrip":return M.SubRip;case"ssa":return M.SubStationAlpha;case"ass":return M.SubStationAlphav4;case"ttml":return M.TimedTextMarkupLang;case"vtt":return M.WebVTT;case"stpp":return M.fTTML;case"wvtt":return M.fVTT;default:throw new Error(`The MIME ${e} is not supported as subtitle codec`)}},at=e=>{let r=st(e);for(let t of r)try{return ot(t)}catch{continue}throw new Error(`No MIME types matched any supported Subtitle Codecs in ${e}`)},ct=(e=[])=>{for(let r of e)if(r.attributes.schemeIdUri==="urn:mpeg:dash:role:2011"&&r.attributes.value==="caption")return!0;return!1},ut=(e=[])=>{for(let r of e){let{schemeIdUri:t,value:s}=r.attributes;if(t==="urn:tva:metadata:cs:AudioPurposeCS:2007"&&s==="2")return!0}return!1},lt=(e=[])=>{for(let r of e)if(r.attributes.schemeIdUri==="urn:mpeg:dash:role:2011"&&(r.attributes.value==="forced-subtitle"||r.attributes.value==="forced_subtitle"))return!0;return!1},dt=({id:e,label:r,bitrate:t,duration:s,type:n,codec:i,isClosedCaption:o,isSdh:a,isForced:c,language:l,segments:h})=>{let d=nt(Number(t)),u=s?it(Number(t),Number(s)):void 0;return{id:e,label:r,bitrate:d,size:u,type:n,codec:i,isClosedCaption:o,isSdh:a,isForced:c,segments:h,language:l,toString(){return["SUBTITLE",`[${i}]`,l].join(" | ")}}};he.exports={parseSubtitleCodec:at,checkIsClosedCaption:ct,checkIsSdh:ut,checkIsForced:lt,createSubtitleTrack:dt}});var me=R((Rr,fe)=>{"use strict";var pt=ee(),{parseDuration:ht,isLanguageTagValid:gt}=D(),{parseVideoCodec:ft,parseDynamicRange:mt,createVideoTrack:Ct}=Y(),{parseAudioCodec:bt,createAudioTrack:St,getDolbyDigitalPlusComplexityIndex:vt,checkIsDescriptive:At}=j(),{parseSubtitleCodec:wt,checkIsClosedCaption:Tt,checkIsSdh:yt,checkIsForced:Nt,createSubtitleTrack:Bt}=ge(),{createResolutionFilter:Ut,createVideoQualityFilter:_t,createAudioLanguageFilter:Rt,createSubtitleLanguageFilter:Et,createVideoCodecFilter:Lt,createAudioCodecFilter:It,createAudioChannelsFilter:Dt}=k(),W=e=>e&&(Array.isArray(e)?e.get=r=>W(e.find(t=>t.tagName===r)):(e.getAttr=r=>e.attributes[r],e.getChild=r=>{let t=e.children.find(n=>n.tagName===r);return!r&&typeof e.children?.[0]=="string"?e.children[0]:W(t)},e.set=(r,t)=>e.attributes[r]=t,e.get=r=>e.getAttr(r)||e.getChild(r),e.getNumber=r=>Number(e.find(r)),e.getAll=r=>e.children.filter(t=>t.tagName===r).map(W),e.getBaseUrls=()=>e.getAll("BaseURL").map(r=>r.children[0]),e.getBaseUrl=()=>e.getBaseUrls()[0]),e),Ft=(e,r)=>{let t=e.get,s=e.getAll,n=o=>t(o)||r.get(o),i=o=>[...s(o),...r.getAll(o)].filter(Boolean);return e.get=n,e.getAll=i,{get:n,getAll:i}},Mt=(e,r,t,s)=>{let n=r.getBaseUrl();return n?n.startsWith("https://")||(n=new URL(n,e).toString()):n=e,(t.getBaseUrl()||n)&&(n=new URL(t.getBaseUrl()||"",n).toString()),new URL(s.getBaseUrl()||"",n).toString()},Ot=e=>{let r=e.get("mimeType"),t=e.get("contentType")||r?.split("/")[0];if(!t&&!r)throw new Error("Unable to determine the format of a Representation, cannot continue...");return{contentType:t,mimeType:r}},Pt=(e,r,t)=>r==="text"&&!t.includes("mp4")?t.split("/")[1]:e.get("codecs"),kt=(e,r,t)=>{let s="",n=[],i=e.get("lang"),o=e.get("id");if(e&&(n.push(i),o)){let a=o.match(/\w+_(\w+)=\d+/);a&&a[1]&&n.push(a[1])}n.push(r.get("lang")),t&&n.push(t);for(let a of n){let c=(a||"").trim();!gt(c)||c.startsWith("und")||(s=c)}return s},K=(e,r)=>{let t=e;for(let[s,n]of Object.entries(r))t=t.replace("$"+s+"$",n);return t},Vt=(e,r,t)=>{for(let s of["initialization","media"]){let n=e.get(s);if(n){if(!n.startsWith("https://")){if(!r)throw new Error("Resolved Segment URL is not absolute, and no Base URL is available.");n=new URL(n,r).toString()}if(!new URL(n).search){let i=new URL(t).search;i&&(n+=`?${i}`)}e.set(s,n)}}},$t=(e,r,t,s)=>{let n=[],i=0;for(let c of e.getAll("S")){let l=Number(c.get("t")),h=Number(c.get("r")||0),d=Number(c.get("d"));l&&(i=l);for(let u=0;u<h+1;u++)n.push(i),i+=d}let o=[],a=[...Array(n.length).keys()].map(c=>c+s);for(let c=0;c<n.length;c++){let l=n[c],h=a[c],d=K(r.get("media"),{Bandwidth:t.get("bandwidth"),RepresentationID:t.get("id"),Number:h,Time:l});o.push({url:d})}return o},Gt=(e,r,t,s,n)=>{let i=Number(e.get("startNumber")||1),o=e.get("SegmentTimeline");Vt(e,r,t);let a=parseFloat(e.get("duration")),c=parseFloat(e.get("timescale")||1),h=s?Math.ceil(s/(a/c)):35,d=n.get("bandwidth"),u=n.get("id"),p=[];if(o)p.push(...$t(o,e,n,i));else for(let S=i;S<i+h;S++){let v=K(e.get("media"),{Bandwidth:d,RepresentationID:u,Number:S,Time:S});p.push({url:v})}let C=e.get("initialization");if(C){let S=K(C,{Bandwidth:d,RepresentationID:u});p.unshift({url:S,init:!0})}return p},qt=(e,r)=>{let t=e.get("SegmentURL"),s=[];for(let n of t){let i=n.get("media");i?i.startsWith("https://")||(i=new URL(i,r).toString()):i=r,s.push({url:i,range:n.get("mediaRange")})}return s},Wt=async(e,r)=>{let t=e.get("Initialization");return{url:r,range:""}},Ht=e=>{for(let r of e)if(r.url.includes("&amp;")){let s=new URL(r.url),n=new URLSearchParams(s.searchParams.toString()).entries();for(let[i,o]of n)s.searchParams.delete(i),s.searchParams.append(i.replaceAll("amp;",""),o);r.url=s.toString()}},Qt={"urn:mpeg:dash:mp4protection:2011":"common","urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":"playready","urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed":"widevine"},Yt=e=>{let r={};for(let t of e){let s=t.get("schemeIdUri")?.toLowerCase(),n=t.get("value"),i=t.get("cenc:pssh")?.get(),o=t.get("cenc:default_KID"),a={id:s,value:n,pssh:i,defaultKeyId:o};r[Qt[s]]=a}return r},zt=async(e,r,t)=>{let s=W(pt.parse(e)).get("MPD"),n=s.get("Period"),i=n.get("duration")||s.get("mediaPresentationDuration"),o=ht(i),a=[],c=[],l=[];for(let h of n.getAll("AdaptationSet"))for(let d of h.getAll("Representation")){let{get:u,getAll:p}=Ft(d,h),{contentType:C,mimeType:S}=Ot(d),v=Pt(d,C,S),O=kt(d,h,t),U=Mt(r,s,n,d),V=u("SegmentTemplate"),G=u("SegmentList"),L=u("SegmentBase"),T=[];if(V){let w=Gt(V,U,r,o,d);T.push(...w)}else if(G){let w=qt(G,U);T.push(...w)}else if(L){let w=await Wt(L,U);T.push(w)}else if(U)T.push({url:U});else throw new Error("Could not find a way to get segments from this MPD manifest.");Ht(T);let $=u("label"),y=u("frameRate")??L?.attributes.timescale,g=u("width")??0,f=u("height")??0,A=u("bandwidth"),B=p("SupplementalProperty"),I=p("EssentialProperty"),m=h.getAll("Accessibility"),N=h.getAll("Role"),_=p("ContentProtection"),b=[new URL(U).hostname,C,v,A,O,s.get("id"),n.get("id"),u("id"),u("audioTrackId")].filter(Boolean).join("-").replaceAll("/","-");switch(C){case"video":{let w=Ct({id:b,label:$,type:C,codec:ft(v),dynamicRange:mt(v,B,I),contentProtection:Yt(_),bitrate:A,duration:o,width:g,height:f,fps:y,language:O,segments:T});a.push(w);break}case"audio":{let w=St({id:b,label:$,type:C,codec:bt(v),channels:u("AudioChannelConfiguration")?.get("value"),jointObjectCoding:vt(B),isDescriptive:At(m),bitrate:A,duration:o,language:O,segments:T});c.push(w);break}case"text":{let w=Bt({id:b,label:$,type:C,codec:wt(v||"vtt"),isClosedCaption:Tt(N),isSdh:yt(m),isForced:Nt(N),bitrate:A,duration:o,language:O,segments:T});l.push(w);break}case"image":break;default:throw new Error(`Unknown content type: ${C}`)}}return a.sort((h,d)=>d.bitrate.bps-h.bitrate.bps),{duration:o,tracks:{all:a.concat(c).concat(l),videos:a,audios:c,subtitles:l,withResolution:Ut(a),withVideoCodecs:Lt(a),withVideoQuality:_t(a),withAudioCodecs:It(c),withAudioLanguages:Rt(c),withAudioChannels:Dt(c),withSubtitleLanguages:Et(l)}}};fe.exports={parseManifest:zt}});var Ae=R((Er,ve)=>{"use strict";var{dirname:jt,basename:Ce}=require("path"),Kt=require("m3u8-parser"),{parseBitrate:Xt,getQualityLabel:Jt}=D(),{createResolutionFilter:xt,createVideoQualityFilter:Zt,createAudioLanguageFilter:er,createSubtitleLanguageFilter:tr,createVideoCodecFilter:rr,createAudioCodecFilter:sr,createAudioChannelsFilter:nr}=k(),{createAudioTrack:ir}=j(),{createVideoTrack:or}=Y(),be=e=>{let r=new Kt.Parser;return r.push(e),r.end(),r.manifest},ar=async e=>{let r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch playlist (${r.status}): ${e}`);let t=await r.text();return be(t)},x=(e,r)=>{let t=e;return t.startsWith("https://")||(t=new URL(t,r).toString()+new URL(r).search),t},cr=(e,r)=>new URL(e).pathname===new URL(r).pathname,Se=(e,r)=>{let t=[];if(!e)return t;for(let[s,n]of Object.entries(e))for(let[i,o]of Object.entries(n)){let a=x(o.uri,r);t.find(l=>cr(l.url,a))||t.push({groupId:s,id:o.uri.replace("/",""),type:s,label:i,language:o.language,url:a,default:o.default})}return t},ur=(e,r)=>e.mediaGroups?Se(e.mediaGroups.AUDIO,r):[],lr=(e,r)=>e.mediaGroups?Se(e.mediaGroups.SUBTITLES,r):[],dr=(e,r)=>e.playlists?e.playlists.map(t=>{let s=t.attributes?.BANDWIDTH,n=t.resolvedUri||x(t.uri,r),i={id:t.uri.replace("/",""),bitrate:Xt(s),url:n};return i.type="video",t.attributes.RESOLUTION&&(i.resolution=t.attributes.RESOLUTION,i.quality=Jt(i.resolution)),t.attributes["VIDEO-RANGE"]&&(i.dynamicRange=t.attributes["VIDEO-RANGE"]),t.attributes.CODECS&&(i.codecs=t.attributes.CODECS),t.attributes["FRAME-RATE"]&&(i.frameRate=t.attributes["FRAME-RATE"]),i}):[],pr=(e=[],r)=>{let t=i=>{let o=i.resolvedUri||i.uri;if(!o.startsWith("https://")&&r.url){let a=jt(r.url)+"/";o=new URL(o,a).toString()}return{url:o,duration:i.duration,number:i.number,presentationTime:i.presentationTime}},s=e.map(t),n=e[0].map;if(e.length&&(n?.resolvedUri||n?.uri)){let i=n?.resolvedUri||x(n.uri,r.url);s.unshift({url:i,init:!0,duration:0,number:0,presentationTime:0})}return s},J=(e,r)=>{if(r.segments=pr(e.segments,r),e.contentProtection){r.protection={};let t=e.contentProtection["com.apple.fps.1_0"];t&&(r.protection.fairplay={keyFormat:t.attributes.KEYFORMAT,uri:t.attributes.URI,method:t.attributes.METHOD});let s=e.contentProtection["com.widevine.alpha"];s&&(r.protection.widevine={pssh:s.pssh,uri:s.attributes.schemeIdUri,keyId:s.attributes.keyId})}},X=e=>Promise.all(e.map(async r=>{let t=await ar(r.url);J(t,r)})),hr=async(e,r)=>{let t=be(e),s=dr(t,r),n=ur(t,r),i=lr(t,r);if(!t.playlists&&t.segments){let{pathname:a}=new URL(r);if(a.includes(".m4a")||a.includes(".mp3")||a.includes(".opus")){let l=ir({id:"audio"+Ce(a),label:"audio",type:"audio",codec:"",channels:2,jointObjectCoding:"",isDescriptive:!1,bitrate:NaN,duration:NaN,language:""});J(t,l),n.push(l)}else{let l=or({id:"video"+Ce(a),label:"video",type:"video",codec:"",dynamicRange:"",contentProtection:"",bitrate:NaN,duration:NaN,width:NaN,height:NaN,fps:NaN,language:""});J(t,l),s.push(l)}}else await Promise.all([X(s),X(n),X(i)]);return{tracks:{all:s.concat(n).concat(i),videos:s,audios:n,subtitles:i,withResolution:xt(s),withVideoCodecs:rr(s),withVideoQuality:Zt(s),withAudioCodecs:sr(n),withAudioLanguages:er(n),withAudioChannels:nr(n),withSubtitleLanguages:tr(i)}}};ve.exports={parseManifest:hr}});var gr=me(),fr=Ae(),{filterByResolution:mr,filterByQuality:Cr,filterByCodecs:br,filterByLanguages:Sr,filterByChannels:vr}=k(),Ar=(e,r,t)=>{if(e.includes("<MPD"))return gr.parseManifest(e,r,t);if(e.includes("#EXTM3U"))return fr.parseManifest(e,r);throw new Error("Invalid manifest")};module.exports={parse:Ar,filterByResolution:mr,filterByQuality:Cr,filterByCodecs:br,filterByLanguages:Sr,filterByChannels:vr};
1
+ "use strict";
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __commonJS = (cb, mod) => function __require() {
4
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
5
+ };
6
+
7
+ // lib/xml.js
8
+ var require_xml = __commonJS({
9
+ "lib/xml.js"(exports2, module2) {
10
+ "use strict";
11
+ function parse2(text, options = {}) {
12
+ var pos = options.pos || 0;
13
+ var keepComments = !!options.keepComments;
14
+ var keepWhitespace = !!options.keepWhitespace;
15
+ var openBracket = "<";
16
+ var openBracketCC = "<".charCodeAt(0);
17
+ var closeBracket = ">";
18
+ var closeBracketCC = ">".charCodeAt(0);
19
+ var minusCC = "-".charCodeAt(0);
20
+ var slashCC = "/".charCodeAt(0);
21
+ var exclamationCC = "!".charCodeAt(0);
22
+ var singleQuoteCC = "'".charCodeAt(0);
23
+ var doubleQuoteCC = '"'.charCodeAt(0);
24
+ var openCornerBracketCC = "[".charCodeAt(0);
25
+ var closeCornerBracketCC = "]".charCodeAt(0);
26
+ function parseChildren(tagName) {
27
+ var children = [];
28
+ while (text[pos]) {
29
+ if (text.charCodeAt(pos) == openBracketCC) {
30
+ if (text.charCodeAt(pos + 1) === slashCC) {
31
+ var closeStart = pos + 2;
32
+ pos = text.indexOf(closeBracket, pos);
33
+ var closeTag = text.substring(closeStart, pos);
34
+ if (closeTag.indexOf(tagName) == -1) {
35
+ const parsedText = text.substring(0, pos).split("\n");
36
+ throw new Error(
37
+ "Unexpected close tag\nLine: " + (parsedText.length - 1) + "\nColumn: " + (parsedText[parsedText.length - 1].length + 1) + "\nChar: " + text[pos]
38
+ );
39
+ }
40
+ if (pos + 1) pos += 1;
41
+ return children;
42
+ } else if (text.charCodeAt(pos + 1) === exclamationCC) {
43
+ if (text.charCodeAt(pos + 2) == minusCC) {
44
+ const startCommentPos = pos;
45
+ while (pos !== -1 && !(text.charCodeAt(pos) === closeBracketCC && text.charCodeAt(pos - 1) == minusCC && text.charCodeAt(pos - 2) == minusCC && pos != -1)) {
46
+ pos = text.indexOf(closeBracket, pos + 1);
47
+ }
48
+ if (pos === -1) {
49
+ pos = text.length;
50
+ }
51
+ if (keepComments) {
52
+ children.push(text.substring(startCommentPos, pos + 1));
53
+ }
54
+ } else if (text.charCodeAt(pos + 2) === openCornerBracketCC && text.charCodeAt(pos + 8) === openCornerBracketCC && text.substr(pos + 3, 5).toLowerCase() === "cdata") {
55
+ var cdataEndIndex = text.indexOf("]]>", pos);
56
+ if (cdataEndIndex == -1) {
57
+ children.push(text.substr(pos + 9));
58
+ pos = text.length;
59
+ } else {
60
+ children.push(text.substring(pos + 9, cdataEndIndex));
61
+ pos = cdataEndIndex + 3;
62
+ }
63
+ continue;
64
+ } else {
65
+ const startDoctype = pos + 1;
66
+ pos += 2;
67
+ var encapsuled = false;
68
+ while ((text.charCodeAt(pos) !== closeBracketCC || encapsuled === true) && text[pos]) {
69
+ if (text.charCodeAt(pos) === openCornerBracketCC) {
70
+ encapsuled = true;
71
+ } else if (encapsuled === true && text.charCodeAt(pos) === closeCornerBracketCC) {
72
+ encapsuled = false;
73
+ }
74
+ pos++;
75
+ }
76
+ children.push(text.substring(startDoctype, pos));
77
+ }
78
+ pos++;
79
+ continue;
80
+ }
81
+ var node = parseNode();
82
+ children.push(node);
83
+ if (node.tagName[0] === "?") {
84
+ children.push(...node.children);
85
+ node.children = [];
86
+ }
87
+ } else {
88
+ const parsedText = parseText();
89
+ if (keepWhitespace) {
90
+ if (parsedText.length > 0) {
91
+ children.push(parsedText);
92
+ }
93
+ } else {
94
+ var trimmed = parsedText.trim();
95
+ if (trimmed.length > 0) {
96
+ children.push(trimmed);
97
+ }
98
+ }
99
+ pos++;
100
+ }
101
+ }
102
+ return children;
103
+ }
104
+ function parseText() {
105
+ var start = pos;
106
+ pos = text.indexOf(openBracket, pos) - 1;
107
+ if (pos === -2) pos = text.length;
108
+ return text.slice(start, pos + 1);
109
+ }
110
+ var nameSpacer = "\r\n >/= ";
111
+ function parseName() {
112
+ var start = pos;
113
+ while (nameSpacer.indexOf(text[pos]) === -1 && text[pos]) {
114
+ pos++;
115
+ }
116
+ return text.slice(start, pos);
117
+ }
118
+ var NoChildNodes = options.noChildNodes || [
119
+ "img",
120
+ "br",
121
+ "input",
122
+ "meta",
123
+ "link",
124
+ "hr"
125
+ ];
126
+ function parseNode() {
127
+ pos++;
128
+ const tagName = parseName();
129
+ const attributes = {};
130
+ let children = [];
131
+ while (text.charCodeAt(pos) !== closeBracketCC && text[pos]) {
132
+ var c = text.charCodeAt(pos);
133
+ if (c > 64 && c < 91 || c > 96 && c < 123) {
134
+ var name = parseName();
135
+ var code = text.charCodeAt(pos);
136
+ while (code && code !== singleQuoteCC && code !== doubleQuoteCC && !(code > 64 && code < 91 || code > 96 && code < 123) && code !== closeBracketCC) {
137
+ pos++;
138
+ code = text.charCodeAt(pos);
139
+ }
140
+ if (code === singleQuoteCC || code === doubleQuoteCC) {
141
+ var value = parseString();
142
+ if (pos === -1) {
143
+ return {
144
+ tagName,
145
+ attributes,
146
+ children
147
+ };
148
+ }
149
+ } else {
150
+ value = null;
151
+ pos--;
152
+ }
153
+ attributes[name] = value;
154
+ }
155
+ pos++;
156
+ }
157
+ if (text.charCodeAt(pos - 1) !== slashCC) {
158
+ if (tagName == "script") {
159
+ const start = pos + 1;
160
+ pos = text.indexOf("</script>", pos);
161
+ children = [text.slice(start, pos)];
162
+ pos += 9;
163
+ } else if (tagName == "style") {
164
+ const start = pos + 1;
165
+ pos = text.indexOf("</style>", pos);
166
+ children = [text.slice(start, pos)];
167
+ pos += 8;
168
+ } else if (NoChildNodes.indexOf(tagName) === -1) {
169
+ pos++;
170
+ children = parseChildren(tagName);
171
+ } else {
172
+ pos++;
173
+ }
174
+ } else {
175
+ pos++;
176
+ }
177
+ return {
178
+ tagName,
179
+ attributes,
180
+ children
181
+ };
182
+ }
183
+ function parseString() {
184
+ var startChar = text[pos];
185
+ var startpos = pos + 1;
186
+ pos = text.indexOf(startChar, startpos);
187
+ return text.slice(startpos, pos);
188
+ }
189
+ function findElements() {
190
+ var r = new RegExp(
191
+ "\\s" + options.attrName + `\\s*=['"]` + options.attrValue + `['"]`
192
+ ).exec(text);
193
+ if (r) {
194
+ return r.index;
195
+ } else {
196
+ return -1;
197
+ }
198
+ }
199
+ let out = null;
200
+ if (options.attrValue !== void 0) {
201
+ options.attrName = options.attrName || "id";
202
+ out = [];
203
+ while ((pos = findElements()) !== -1) {
204
+ pos = text.lastIndexOf("<", pos);
205
+ if (pos !== -1) {
206
+ out.push(parseNode());
207
+ }
208
+ text = text.substr(pos);
209
+ pos = 0;
210
+ }
211
+ } else if (options.parseNode) {
212
+ out = parseNode();
213
+ } else {
214
+ out = parseChildren("");
215
+ }
216
+ if (options.filter) {
217
+ out = filter(out, options.filter);
218
+ }
219
+ if (options.setPos) {
220
+ out.pos = pos;
221
+ }
222
+ return out;
223
+ }
224
+ function filter(children, f, dept = 0, path = "") {
225
+ var out = [];
226
+ children.forEach(function(child, i) {
227
+ if (typeof child === "object" && f(child, i, dept, path)) out.push(child);
228
+ if (child.children) {
229
+ var kids = filter(
230
+ child.children,
231
+ f,
232
+ dept + 1,
233
+ (path ? path + "." : "") + i + "." + child.tagName
234
+ );
235
+ out = out.concat(kids);
236
+ }
237
+ });
238
+ return out;
239
+ }
240
+ module2.exports = { parse: parse2, filter };
241
+ }
242
+ });
243
+
244
+ // lib/util.js
245
+ var require_util = __commonJS({
246
+ "lib/util.js"(exports2, module2) {
247
+ "use strict";
248
+ var formatBytes = (bytes, sizes = ["Bytes", "KB", "MB", "GB", "TB"]) => {
249
+ if (bytes == 0) return `0 ${sizes[0]}`;
250
+ const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
251
+ if (i == 0) return bytes + " " + sizes[i];
252
+ return (bytes / Math.pow(1024, i)).toFixed(1) + " " + sizes[i];
253
+ };
254
+ var parseSize = (bandwidth, duration) => ({
255
+ b: bandwidth * duration,
256
+ kb: bandwidth / 1e3 * duration,
257
+ mb: bandwidth / 8e6 * duration,
258
+ gb: bandwidth / 8e9 * duration,
259
+ toString() {
260
+ return formatBytes(bandwidth * duration);
261
+ }
262
+ });
263
+ var parseBitrate = (bandwidth) => ({
264
+ bps: bandwidth,
265
+ kbps: bandwidth / 1e3,
266
+ mbps: bandwidth / 8e6,
267
+ gbps: bandwidth / 8e9,
268
+ toString() {
269
+ return formatBytes(bandwidth, ["bps", "Kbps", "Mbps", "Gbps"]);
270
+ }
271
+ });
272
+ var qualities = [
273
+ { width: 7680, height: 4320 },
274
+ { width: 3840, height: 2160 },
275
+ { width: 2560, height: 1440 },
276
+ { width: 1920, height: 1080 },
277
+ { width: 1280, height: 720 },
278
+ { width: 1024, height: 576 },
279
+ { width: 854, height: 480 },
280
+ { width: 640, height: 360 },
281
+ { width: 426, height: 240 },
282
+ { width: 256, height: 144 }
283
+ ];
284
+ var getWidth = (height) => qualities.find((q) => q.height === height)?.width;
285
+ var getHeight = (width) => qualities.find((q) => q.width === width)?.height;
286
+ var getQualityLabel = (resolution) => `${getHeight(resolution.width) || resolution.height}p`;
287
+ var getBestTrack = (tracks) => {
288
+ const maxBitrate = Math.max(...tracks.map((track) => track.bitrate.bps));
289
+ return tracks.find((track) => track.bitrate.bps === maxBitrate);
290
+ };
291
+ var parseDuration = (str) => {
292
+ const SECONDS_IN_YEAR = 365 * 24 * 60 * 60;
293
+ const SECONDS_IN_MONTH = 30 * 24 * 60 * 60;
294
+ const SECONDS_IN_DAY = 24 * 60 * 60;
295
+ const SECONDS_IN_HOUR = 60 * 60;
296
+ const SECONDS_IN_MIN = 60;
297
+ const durationRegex = /P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/;
298
+ const match = durationRegex.exec(str);
299
+ if (!match) {
300
+ return 0;
301
+ }
302
+ const [year, month, day, hour, minute, second] = match.slice(1);
303
+ return parseFloat(year || 0) * SECONDS_IN_YEAR + parseFloat(month || 0) * SECONDS_IN_MONTH + parseFloat(day || 0) * SECONDS_IN_DAY + parseFloat(hour || 0) * SECONDS_IN_HOUR + parseFloat(minute || 0) * SECONDS_IN_MIN + parseFloat(second || 0);
304
+ };
305
+ var isLanguageTagValid = (value) => {
306
+ try {
307
+ Intl.getCanonicalLocales(value);
308
+ return true;
309
+ } catch (e) {
310
+ return;
311
+ }
312
+ };
313
+ module2.exports = {
314
+ parseSize,
315
+ parseBitrate,
316
+ getWidth,
317
+ getHeight,
318
+ getQualityLabel,
319
+ getBestTrack,
320
+ parseDuration,
321
+ isLanguageTagValid
322
+ };
323
+ }
324
+ });
325
+
326
+ // lib/video.js
327
+ var require_video = __commonJS({
328
+ "lib/video.js"(exports2, module2) {
329
+ "use strict";
330
+ var { parseBitrate, getQualityLabel, parseSize } = require_util();
331
+ var VIDEO_CODECS = {
332
+ avc: "H.264",
333
+ hevc: "H.265",
334
+ vc1: "VC-1",
335
+ vp8: "VP8",
336
+ vp9: "VP9",
337
+ av1: "AV1"
338
+ };
339
+ var DYNAMIC_RANGE = {
340
+ sdr: "SDR",
341
+ // Standart Dynamic Range
342
+ hlg: "HLG",
343
+ // Hybrid log-gamma (HDR)
344
+ hdr10: "HDR10",
345
+ hdr10p: "HDR10+",
346
+ dv: "DV"
347
+ // Dolby Vision
348
+ };
349
+ var PRIMARIES = {
350
+ Unspecified: 0,
351
+ BT_709: 1,
352
+ BT_601_625: 5,
353
+ BT_601_525: 6,
354
+ BT_2020_and_2100: 9,
355
+ SMPTE_ST_2113_and_EG_4321: 12
356
+ // P3D65
357
+ };
358
+ var TRANSFER = {
359
+ Unspecified: 0,
360
+ BT_709: 1,
361
+ BT_601: 6,
362
+ BT_2020: 14,
363
+ BT_2100: 15,
364
+ BT_2100_PQ: 16,
365
+ BT_2100_HLG: 18
366
+ };
367
+ var MATRIX = {
368
+ RGB: 0,
369
+ YCbCr_BT_709: 1,
370
+ YCbCr_BT_601_625: 5,
371
+ YCbCr_BT_601_525: 6,
372
+ YCbCr_BT_2020_and_2100: 9,
373
+ // YCbCr BT.2100 shares the same CP
374
+ ICtCp_BT_2100: 14
375
+ };
376
+ var parseVideoCodecFromMime = (mime) => {
377
+ const target = mime.toLowerCase().trim().split(".")[0];
378
+ const avc = ["avc1", "avc2", "avc3", "dva1", "dvav"];
379
+ const hevc = [
380
+ "hev1",
381
+ "hev2",
382
+ "hev3",
383
+ "hvc1",
384
+ "hvc2",
385
+ "hvc3",
386
+ "dvh1",
387
+ "dvhe",
388
+ "lhv1",
389
+ "lhe1"
390
+ ];
391
+ const vc1 = ["vc-1"];
392
+ const vp8 = ["vp08", "vp8"];
393
+ const vp9 = ["vp09", "vp9"];
394
+ const av1 = ["av01"];
395
+ if (avc.includes(target)) return VIDEO_CODECS.avc;
396
+ if (hevc.includes(target)) return VIDEO_CODECS.hevc;
397
+ if (vc1.includes(target)) return VIDEO_CODECS.hevc;
398
+ if (vp8.includes(target)) return VIDEO_CODECS.vp8;
399
+ if (vp9.includes(target)) return VIDEO_CODECS.vp9;
400
+ if (av1.includes(target)) return VIDEO_CODECS.av1;
401
+ throw new Error(`The MIME ${mime} is not supported as video codec`);
402
+ };
403
+ var parseDynamicRangeFromCicp = (primaries, transfer, matrix) => {
404
+ if (transfer == 5) transfer = TRANSFER.BT_601;
405
+ if (primaries == PRIMARIES.Unspecified && transfer == TRANSFER.Unspecified && matrix == MATRIX.RGB)
406
+ return DYNAMIC_RANGE.sdr;
407
+ else if ([PRIMARIES.BT_601_625, PRIMARIES.BT_601_525].includes(primaries))
408
+ return DYNAMIC_RANGE.sdr;
409
+ else if (TRANSFER.BT_2100_PQ === transfer) return DYNAMIC_RANGE.hdr10;
410
+ else if (TRANSFER.BT_2100_HLG === transfer) return DYNAMIC_RANGE.hlg;
411
+ else return DYNAMIC_RANGE.sdr;
412
+ };
413
+ var createVideoTrack = ({
414
+ id,
415
+ label,
416
+ type,
417
+ codec,
418
+ dynamicRange,
419
+ contentProtection,
420
+ bitrate,
421
+ duration,
422
+ width,
423
+ height,
424
+ fps,
425
+ language,
426
+ segments
427
+ }) => {
428
+ const parsedBitrate = parseBitrate(Number(bitrate));
429
+ const parsedWidth = Number(width);
430
+ const parsedHeight = Number(height);
431
+ const size = duration ? parseSize(Number(bitrate), Number(duration)) : void 0;
432
+ return {
433
+ id,
434
+ label,
435
+ type,
436
+ codec,
437
+ bitrate: parsedBitrate,
438
+ size,
439
+ protection: contentProtection,
440
+ segments,
441
+ dynamicRange,
442
+ language,
443
+ width: parsedWidth,
444
+ height: parsedHeight,
445
+ fps: Number(fps),
446
+ quality: getQualityLabel({ width: parsedWidth, height: parsedHeight }),
447
+ toString() {
448
+ return [
449
+ "VIDEO",
450
+ `[${codec}, ${dynamicRange}]`,
451
+ language,
452
+ `${width}x${height} @ ${parsedBitrate.kbps} kb/s, ${fps} FPS`
453
+ ].join(" | ");
454
+ }
455
+ };
456
+ };
457
+ var parseVideoCodec = (codecs) => {
458
+ for (const codec of codecs.toLowerCase().split(",")) {
459
+ const mime = codec.trim().split(".")[0];
460
+ try {
461
+ return parseVideoCodecFromMime(mime);
462
+ } catch (e) {
463
+ continue;
464
+ }
465
+ }
466
+ throw new Error(
467
+ `No MIME types matched any supported Video Codecs in ${codecs}`
468
+ );
469
+ };
470
+ var parseDynamicRange = (codecs, supplementalProps = [], essentialProps = []) => {
471
+ const dv = ["dva1", "dvav", "dvhe", "dvh1"];
472
+ if (dv.some((value) => codecs.startsWith(value))) return DYNAMIC_RANGE.dv;
473
+ const primariesScheme = "urn:mpeg:mpegB:cicp:ColourPrimaries";
474
+ const transferScheme = "urn:mpeg:mpegB:cicp:TransferCharacteristics";
475
+ const matrixScheme = "urn:mpeg:mpegB:cicp:MatrixCoefficients";
476
+ const allProps = [...essentialProps, ...supplementalProps];
477
+ const getValues = (scheme) => allProps.filter((prop) => prop.attributes.schemeIdUri === scheme).map((prop) => parseInt(prop.attributes.value));
478
+ const primaries = getValues(primariesScheme).reduce(
479
+ (acc, current) => acc + current,
480
+ 0
481
+ );
482
+ const transfer = getValues(transferScheme).reduce(
483
+ (acc, current) => acc + current,
484
+ 0
485
+ );
486
+ const matrix = getValues(matrixScheme).reduce(
487
+ (acc, current) => acc + current,
488
+ 0
489
+ );
490
+ return parseDynamicRangeFromCicp(primaries, transfer, matrix);
491
+ };
492
+ module2.exports = {
493
+ parseVideoCodec,
494
+ parseDynamicRange,
495
+ createVideoTrack,
496
+ VIDEO_CODECS
497
+ };
498
+ }
499
+ });
500
+
501
+ // lib/track.js
502
+ var require_track = __commonJS({
503
+ "lib/track.js"(exports2, module2) {
504
+ "use strict";
505
+ var { getBestTrack } = require_util();
506
+ var parseMimes = (codecs) => codecs.toLowerCase().split(",").map((codec) => codec.trim().split(".")[0]);
507
+ var createResolutionFilter = (videos) => {
508
+ return ({ width, height }) => {
509
+ return videos.filter(
510
+ (track) => (!width || track.width === width) && (!height || track.height === height)
511
+ );
512
+ };
513
+ };
514
+ var createCodecFilter = (tracks) => {
515
+ return (codecs) => {
516
+ if (!codecs?.length) return tracks;
517
+ const results = tracks.filter((track) => codecs.includes(track.codec));
518
+ results.sort((a, b) => b.bitrate.bps - a.bitrate.bps);
519
+ return results;
520
+ };
521
+ };
522
+ var createVideoCodecFilter = (videos) => createCodecFilter(videos);
523
+ var createVideoQualityFilter = (videos) => {
524
+ return (quality) => {
525
+ if (!quality) return [getBestTrack(videos)];
526
+ const trackQuality = String(quality).includes("p") ? quality : `${quality}p`;
527
+ const results = videos.filter((track) => track.quality === trackQuality);
528
+ results.sort((a, b) => b.bitrate.bps - a.bitrate.bps);
529
+ return results.length ? results : [getBestTrack(videos)];
530
+ };
531
+ };
532
+ var createAudioCodecFilter = (audios) => createCodecFilter(audios);
533
+ var createAudioLanguageFilter = (audios) => {
534
+ return (languages = [], maxTracksPerLanguage) => {
535
+ if (!languages.length) {
536
+ const audiosWithLanguage = audios.filter((track) => track.language);
537
+ if (audiosWithLanguage.length) {
538
+ for (const audio of audiosWithLanguage) {
539
+ const alreadyAdded = languages.includes(audio.language);
540
+ if (!alreadyAdded) languages.push(audio.language);
541
+ }
542
+ } else {
543
+ audios.sort((a, b) => b.bitrate.bps - a.bitrate.bps);
544
+ return audios.slice(0, maxTracksPerLanguage);
545
+ }
546
+ }
547
+ const filtered = [];
548
+ for (const language of languages) {
549
+ const tracks = audios.filter(
550
+ (track) => track.language?.startsWith(language)
551
+ );
552
+ filtered.push(...tracks);
553
+ }
554
+ const results = [];
555
+ const filteredLanguages = [
556
+ ...new Set(filtered.map((track) => track.language))
557
+ ];
558
+ for (const language of filteredLanguages) {
559
+ const tracks = filtered.filter((track) => track.language === language).slice(0, maxTracksPerLanguage);
560
+ results.push(...tracks);
561
+ }
562
+ return results;
563
+ };
564
+ };
565
+ var createAudioChannelsFilter = (audios) => {
566
+ return (channels) => {
567
+ if (!channels) return audios;
568
+ const value = typeof channels === "string" ? parseFloat(channels) : channels;
569
+ return audios.filter((track) => track.channels === value);
570
+ };
571
+ };
572
+ var createSubtitleLanguageFilter = (subtitles) => {
573
+ return (languages) => {
574
+ if (!languages.length) return subtitles;
575
+ return subtitles.filter(
576
+ (track) => languages.some(
577
+ (language) => track.language?.startsWith(language) || track.label?.startsWith(language)
578
+ )
579
+ );
580
+ };
581
+ };
582
+ var filterByResolution2 = (tracks, resolution) => createResolutionFilter(tracks)(resolution);
583
+ var filterByQuality2 = (tracks, quality) => createVideoQualityFilter(tracks)(quality);
584
+ var filterByCodecs2 = (tracks, codecs) => createCodecFilter(tracks)(codecs);
585
+ var filterByLanguages2 = (tracks, languages, maxTracksPerLanguage) => createAudioLanguageFilter(tracks)(languages, maxTracksPerLanguage);
586
+ var filterByChannels2 = (tracks, channels) => createAudioChannelsFilter(tracks)(channels);
587
+ module2.exports = {
588
+ parseMimes,
589
+ createResolutionFilter,
590
+ createVideoCodecFilter,
591
+ createVideoQualityFilter,
592
+ createAudioCodecFilter,
593
+ createAudioLanguageFilter,
594
+ createAudioChannelsFilter,
595
+ createSubtitleLanguageFilter,
596
+ filterByResolution: filterByResolution2,
597
+ filterByQuality: filterByQuality2,
598
+ filterByCodecs: filterByCodecs2,
599
+ filterByLanguages: filterByLanguages2,
600
+ filterByChannels: filterByChannels2
601
+ };
602
+ }
603
+ });
604
+
605
+ // lib/audio.js
606
+ var require_audio = __commonJS({
607
+ "lib/audio.js"(exports2, module2) {
608
+ "use strict";
609
+ var { parseMimes } = require_track();
610
+ var { parseBitrate, parseSize } = require_util();
611
+ var AUDIO_CODECS = {
612
+ AAC: "AAC",
613
+ // https://wikipedia.org/wiki/Advanced_Audio_Coding
614
+ AC3: "DD",
615
+ // https://wikipedia.org/wiki/Dolby_Digital
616
+ EC3: "DD+",
617
+ // https://wikipedia.org/wiki/Dolby_Digital_Plus
618
+ OPUS: "OPUS",
619
+ // https://wikipedia.org/wiki/Opus_(audio_format)
620
+ OGG: "VORB",
621
+ // https://wikipedia.org/wiki/Vorbis
622
+ DTS: "DTS",
623
+ // https://en.wikipedia.org/wiki/DTS_(company)#DTS_Digital_Surround
624
+ ALAC: "ALAC",
625
+ // https://en.wikipedia.org/wiki/Apple_Lossless_Audio_Codec
626
+ FLAC: "FLAC"
627
+ // https://en.wikipedia.org/wiki/FLAC
628
+ };
629
+ var parseAudioCodecFromMime = (mime) => {
630
+ const target = mime.toLowerCase().trim().split(".")[0];
631
+ switch (target) {
632
+ case "mp4a":
633
+ return AUDIO_CODECS.AAC;
634
+ case "ac-3":
635
+ return AUDIO_CODECS.AC3;
636
+ case "ec-3":
637
+ return AUDIO_CODECS.EC3;
638
+ case "opus":
639
+ return AUDIO_CODECS.OPUS;
640
+ case "dtsc":
641
+ return AUDIO_CODECS.DTS;
642
+ case "alac":
643
+ return AUDIO_CODECS.ALAC;
644
+ case "flac":
645
+ return AUDIO_CODECS.FLAC;
646
+ default:
647
+ throw new Error(`The MIME ${mime} is not supported as audio codec`);
648
+ }
649
+ };
650
+ var parseAudioCodec = (codecs) => {
651
+ const mimes = parseMimes(codecs);
652
+ for (const mime of mimes) {
653
+ try {
654
+ return parseAudioCodecFromMime(mime);
655
+ } catch (e) {
656
+ continue;
657
+ }
658
+ }
659
+ throw new Error(
660
+ `No MIME types matched any supported Audio Codecs in ${codecs}`
661
+ );
662
+ };
663
+ var getDolbyDigitalPlusComplexityIndex = (supplementalProps = []) => {
664
+ const targetScheme = "tag:dolby.com,2018:dash:EC3_ExtensionComplexityIndex:2018";
665
+ for (const prop of supplementalProps)
666
+ if (prop.attributes.schemeIdUri === targetScheme)
667
+ return parseInt(prop.attributes.value);
668
+ };
669
+ var checkIsDescriptive = (accessibilities = []) => {
670
+ for (const accessibility of accessibilities) {
671
+ const { schemeIdUri, value } = accessibility.attributes;
672
+ const firstMatch = schemeIdUri == "urn:mpeg:dash:role:2011" && value === "descriptive";
673
+ const secondMatch = schemeIdUri == "urn:tva:metadata:cs:AudioPurposeCS:2007" && value === "1";
674
+ const isDescriptive = firstMatch || secondMatch;
675
+ if (isDescriptive) return true;
676
+ }
677
+ return false;
678
+ };
679
+ var parseChannels = (channels) => {
680
+ const isDigit = (char) => char >= "0" && char <= "9";
681
+ if (typeof channels === "string") {
682
+ if (channels.toUpperCase() == "A000") return 2;
683
+ else if (channels.toUpperCase() == "F801") return 5.1;
684
+ else if (isDigit(channels.replace("ch", "").replace(".", "")[0]))
685
+ return parseFloat(channels.replace("ch", ""));
686
+ throw new Error(`Unsupported audio channels value, '${channels}'`);
687
+ }
688
+ return parseFloat(channels);
689
+ };
690
+ var createAudioTrack = ({
691
+ id,
692
+ label,
693
+ type,
694
+ codec,
695
+ channels,
696
+ bitrate,
697
+ duration,
698
+ jointObjectCoding = 0,
699
+ isDescriptive = false,
700
+ language,
701
+ segments
702
+ }) => {
703
+ const parsedBitrate = parseBitrate(Number(bitrate));
704
+ const parsedChannels = parseChannels(channels);
705
+ const size = duration ? parseSize(Number(bitrate), Number(duration)) : void 0;
706
+ return {
707
+ id,
708
+ label,
709
+ type,
710
+ codec,
711
+ bitrate: parsedBitrate,
712
+ size,
713
+ language,
714
+ segments,
715
+ channels: parsedChannels,
716
+ jointObjectCoding,
717
+ isDescriptive,
718
+ toString() {
719
+ return [
720
+ "AUDIO",
721
+ `[${codec}]`,
722
+ `${parsedChannels || "?"}` + (jointObjectCoding ? ` (JOC ${jointObjectCoding})` : ""),
723
+ `${parsedBitrate.kbps} kb/s`,
724
+ language
725
+ ].join(" | ");
726
+ }
727
+ };
728
+ };
729
+ module2.exports = {
730
+ AUDIO_CODECS,
731
+ parseAudioCodec,
732
+ createAudioTrack,
733
+ getDolbyDigitalPlusComplexityIndex,
734
+ checkIsDescriptive
735
+ };
736
+ }
737
+ });
738
+
739
+ // lib/subtitle.js
740
+ var require_subtitle = __commonJS({
741
+ "lib/subtitle.js"(exports2, module2) {
742
+ "use strict";
743
+ var { parseMimes } = require_track();
744
+ var { parseBitrate, parseSize } = require_util();
745
+ var SUBTITLE_CODECS = {
746
+ SubRip: "SRT",
747
+ // https://wikipedia.org/wiki/SubRip
748
+ SubStationAlpha: "SSA",
749
+ // https://wikipedia.org/wiki/SubStation_Alpha
750
+ SubStationAlphav4: "ASS",
751
+ // https://wikipedia.org/wiki/SubStation_Alpha#Advanced_SubStation_Alpha=
752
+ TimedTextMarkupLang: "TTML",
753
+ // https://wikipedia.org/wiki/Timed_Text_Markup_Language
754
+ WebVTT: "VTT",
755
+ // https://wikipedia.org/wiki/WebVTT
756
+ // MPEG-DASH box-encapsulated subtitle formats
757
+ fTTML: "STPP",
758
+ // https://www.w3.org/TR/2018/REC-ttml-imsc1.0.1-20180424
759
+ fVTT: "WVTT"
760
+ // https://www.w3.org/TR/webvtt1
761
+ };
762
+ var parseSubtitleCodecFromMime = (mime) => {
763
+ const target = mime.toLowerCase().trim().split(".")[0];
764
+ switch (target) {
765
+ case "srt":
766
+ case "x-subrip":
767
+ return SUBTITLE_CODECS.SubRip;
768
+ case "ssa":
769
+ return SUBTITLE_CODECS.SubStationAlpha;
770
+ case "ass":
771
+ return SUBTITLE_CODECS.SubStationAlphav4;
772
+ case "ttml":
773
+ return SUBTITLE_CODECS.TimedTextMarkupLang;
774
+ case "vtt":
775
+ return SUBTITLE_CODECS.WebVTT;
776
+ case "stpp":
777
+ return SUBTITLE_CODECS.fTTML;
778
+ case "wvtt":
779
+ return SUBTITLE_CODECS.fVTT;
780
+ default:
781
+ throw new Error(`The MIME ${mime} is not supported as subtitle codec`);
782
+ }
783
+ };
784
+ var parseSubtitleCodec = (codecs) => {
785
+ const mimes = parseMimes(codecs);
786
+ for (const mime of mimes) {
787
+ try {
788
+ return parseSubtitleCodecFromMime(mime);
789
+ } catch (e) {
790
+ continue;
791
+ }
792
+ }
793
+ throw new Error(
794
+ `No MIME types matched any supported Subtitle Codecs in ${codecs}`
795
+ );
796
+ };
797
+ var checkIsClosedCaption = (roles = []) => {
798
+ for (const role of roles) {
799
+ const isClosedCaption = role.attributes.schemeIdUri === "urn:mpeg:dash:role:2011" && role.attributes.value === "caption";
800
+ if (isClosedCaption) return true;
801
+ }
802
+ return false;
803
+ };
804
+ var checkIsSdh = (accessibilities = []) => {
805
+ for (const accessibility of accessibilities) {
806
+ const { schemeIdUri, value } = accessibility.attributes;
807
+ const isSdh = schemeIdUri === "urn:tva:metadata:cs:AudioPurposeCS:2007" && value === "2";
808
+ if (isSdh) return true;
809
+ }
810
+ return false;
811
+ };
812
+ var checkIsForced = (roles = []) => {
813
+ for (const role of roles) {
814
+ const isForced = role.attributes.schemeIdUri === "urn:mpeg:dash:role:2011" && (role.attributes.value === "forced-subtitle" || role.attributes.value === "forced_subtitle");
815
+ if (isForced) return true;
816
+ }
817
+ return false;
818
+ };
819
+ var createSubtitleTrack = ({
820
+ id,
821
+ label,
822
+ bitrate,
823
+ duration,
824
+ type,
825
+ codec,
826
+ isClosedCaption,
827
+ isSdh,
828
+ isForced,
829
+ language,
830
+ segments
831
+ }) => {
832
+ const parsedBitrate = parseBitrate(Number(bitrate));
833
+ const size = duration ? parseSize(Number(bitrate), Number(duration)) : void 0;
834
+ return {
835
+ id,
836
+ label,
837
+ bitrate: parsedBitrate,
838
+ size,
839
+ type,
840
+ codec,
841
+ isClosedCaption,
842
+ isSdh,
843
+ isForced,
844
+ segments,
845
+ language,
846
+ toString() {
847
+ return ["SUBTITLE", `[${codec}]`, language].join(" | ");
848
+ }
849
+ };
850
+ };
851
+ module2.exports = {
852
+ parseSubtitleCodec,
853
+ checkIsClosedCaption,
854
+ checkIsSdh,
855
+ checkIsForced,
856
+ createSubtitleTrack
857
+ };
858
+ }
859
+ });
860
+
861
+ // lib/dash.js
862
+ var require_dash = __commonJS({
863
+ "lib/dash.js"(exports2, module2) {
864
+ "use strict";
865
+ var xml = require_xml();
866
+ var { parseDuration, isLanguageTagValid } = require_util();
867
+ var {
868
+ parseVideoCodec,
869
+ parseDynamicRange,
870
+ createVideoTrack
871
+ } = require_video();
872
+ var {
873
+ parseAudioCodec,
874
+ createAudioTrack,
875
+ getDolbyDigitalPlusComplexityIndex,
876
+ checkIsDescriptive
877
+ } = require_audio();
878
+ var {
879
+ parseSubtitleCodec,
880
+ checkIsClosedCaption,
881
+ checkIsSdh,
882
+ checkIsForced,
883
+ createSubtitleTrack
884
+ } = require_subtitle();
885
+ var {
886
+ createResolutionFilter,
887
+ createVideoQualityFilter,
888
+ createAudioLanguageFilter,
889
+ createSubtitleLanguageFilter,
890
+ createVideoCodecFilter,
891
+ createAudioCodecFilter,
892
+ createAudioChannelsFilter
893
+ } = require_track();
894
+ var appendUtils = (element) => {
895
+ if (!element) return element;
896
+ if (Array.isArray(element)) {
897
+ element.get = (name) => appendUtils(element.find((item) => item.tagName === name));
898
+ } else {
899
+ element.getAttr = (name) => element.attributes[name];
900
+ element.getChild = (name) => {
901
+ const tag = element.children.find((item) => item.tagName === name);
902
+ const isString = !name && typeof element.children?.[0] === "string";
903
+ return isString ? element.children[0] : appendUtils(tag);
904
+ };
905
+ element.set = (name, value) => element.attributes[name] = value;
906
+ element.get = (name) => element.getAttr(name) || element.getChild(name);
907
+ element.getNumber = (name) => Number(element.find(name));
908
+ element.getAll = (name) => element.children.filter((item) => item.tagName === name).map(appendUtils);
909
+ element.getBaseUrls = () => element.getAll("BaseURL").map((item) => item.children[0]);
910
+ element.getBaseUrl = () => element.getBaseUrls()[0];
911
+ }
912
+ return element;
913
+ };
914
+ var combineGetters = (representation, adaptationSet) => {
915
+ const prevGet = representation.get;
916
+ const prevGetAll = representation.getAll;
917
+ const get = (name) => prevGet(name) || adaptationSet.get(name);
918
+ const getAll = (name) => [...prevGetAll(name), ...adaptationSet.getAll(name)].filter(Boolean);
919
+ representation.get = get;
920
+ representation.getAll = getAll;
921
+ return { get, getAll };
922
+ };
923
+ var parseBaseUrl = (manifestUrl, mpd, period, representation) => {
924
+ let base = mpd.getBaseUrl();
925
+ if (!base) base = manifestUrl;
926
+ else if (!base.startsWith("https://"))
927
+ base = new URL(base, manifestUrl).toString();
928
+ if (!!period.getBaseUrl() || !!base)
929
+ base = new URL(period.getBaseUrl() || "", base).toString();
930
+ const baseUrl = new URL(representation.getBaseUrl() || "", base).toString();
931
+ return baseUrl;
932
+ };
933
+ var parseContentTypes = (representation) => {
934
+ const mimeType = representation.get("mimeType");
935
+ const contentType = representation.get("contentType") || mimeType?.split("/")[0];
936
+ if (!contentType && !mimeType)
937
+ throw new Error(
938
+ "Unable to determine the format of a Representation, cannot continue..."
939
+ );
940
+ return { contentType, mimeType };
941
+ };
942
+ var parseCodecs = (representation, contentType, mimeType) => {
943
+ const shouldUseCodecsFromMime = contentType === "text" && !mimeType.includes("mp4");
944
+ const codecs = shouldUseCodecsFromMime ? mimeType.split("/")[1] : representation.get("codecs");
945
+ return codecs;
946
+ };
947
+ var parseLanguage = (representation, adaptationSet, fallbackLanguage) => {
948
+ let language = "";
949
+ const options = [];
950
+ const lang = representation.get("lang");
951
+ const id = representation.get("id");
952
+ if (representation) {
953
+ options.push(lang);
954
+ if (id) {
955
+ const m = id.match(/\w+_(\w+)=\d+/);
956
+ if (m && m[1]) options.push(m[1]);
957
+ }
958
+ }
959
+ options.push(adaptationSet.get("lang"));
960
+ if (fallbackLanguage) options.push(fallbackLanguage);
961
+ for (const option of options) {
962
+ const value = (option || "").trim();
963
+ if (!isLanguageTagValid(value) || value.startsWith("und")) continue;
964
+ language = value;
965
+ continue;
966
+ }
967
+ if (!language) {
968
+ }
969
+ return language;
970
+ };
971
+ var buildSegmentUrl = (template, fields) => {
972
+ let result = template;
973
+ for (const [key, value] of Object.entries(fields))
974
+ result = result.replace("$" + key + "$", value);
975
+ return result;
976
+ };
977
+ var resolveSegmentTemplateUrls = (segmentTemplate, baseUrl, manifestUrl) => {
978
+ for (const type of ["initialization", "media"]) {
979
+ let value = segmentTemplate.get(type);
980
+ if (!value) continue;
981
+ if (!value.startsWith("https://")) {
982
+ if (!baseUrl)
983
+ throw new Error(
984
+ `Resolved Segment URL is not absolute, and no Base URL is available.`
985
+ );
986
+ value = new URL(value, baseUrl).toString();
987
+ }
988
+ if (!new URL(value).search) {
989
+ const manifestUrlQuery = new URL(manifestUrl).search;
990
+ if (manifestUrlQuery) value += `?${manifestUrlQuery}`;
991
+ }
992
+ segmentTemplate.set(type, value);
993
+ }
994
+ };
995
+ var parseSegmentsFromTimeline = (segmentTimeline, segmentTemplate, representation, startNumber) => {
996
+ const times = [];
997
+ let currentTime = 0;
998
+ for (const s of segmentTimeline.getAll("S")) {
999
+ const t = Number(s.get("t"));
1000
+ const r = Number(s.get("r") || 0);
1001
+ const d = Number(s.get("d"));
1002
+ if (t) currentTime = t;
1003
+ for (let i = 0; i < r + 1; i++) {
1004
+ times.push(currentTime);
1005
+ currentTime += d;
1006
+ }
1007
+ }
1008
+ const segments = [];
1009
+ const numbers = [...Array(times.length).keys()].map((n) => n + startNumber);
1010
+ for (let i = 0; i < times.length; i++) {
1011
+ const t = times[i];
1012
+ const n = numbers[i];
1013
+ const url = buildSegmentUrl(segmentTemplate.get("media"), {
1014
+ Bandwidth: representation.get("bandwidth"),
1015
+ RepresentationID: representation.get("id"),
1016
+ Number: n,
1017
+ Time: t
1018
+ });
1019
+ segments.push({ url });
1020
+ }
1021
+ return segments;
1022
+ };
1023
+ var parseSegmentsFromTemplate = (segmentTemplate, baseUrl, manifestUrl, duration, representation) => {
1024
+ const startNumber = Number(segmentTemplate.get("startNumber") || 1);
1025
+ const segmentTimeline = segmentTemplate.get("SegmentTimeline");
1026
+ resolveSegmentTemplateUrls(segmentTemplate, baseUrl, manifestUrl);
1027
+ const segmentDuration = parseFloat(segmentTemplate.get("duration"));
1028
+ const segmentTimescale = parseFloat(segmentTemplate.get("timescale") || 1);
1029
+ const DEFAULT_SEGMENTS_COUNT = 35;
1030
+ const segmentsCount = duration ? Math.ceil(duration / (segmentDuration / segmentTimescale)) : DEFAULT_SEGMENTS_COUNT;
1031
+ const bandwidth = representation.get("bandwidth");
1032
+ const id = representation.get("id");
1033
+ const segments = [];
1034
+ if (segmentTimeline) {
1035
+ segments.push(
1036
+ ...parseSegmentsFromTimeline(
1037
+ segmentTimeline,
1038
+ segmentTemplate,
1039
+ representation,
1040
+ startNumber
1041
+ )
1042
+ );
1043
+ } else {
1044
+ for (let i = startNumber; i < startNumber + segmentsCount; i++) {
1045
+ const url = buildSegmentUrl(segmentTemplate.get("media"), {
1046
+ Bandwidth: bandwidth,
1047
+ RepresentationID: id,
1048
+ Number: i,
1049
+ Time: i
1050
+ });
1051
+ segments.push({ url });
1052
+ }
1053
+ }
1054
+ const initialization = segmentTemplate.get("initialization");
1055
+ if (initialization) {
1056
+ const url = buildSegmentUrl(initialization, {
1057
+ Bandwidth: bandwidth,
1058
+ RepresentationID: id
1059
+ });
1060
+ segments.unshift({ url, init: true });
1061
+ }
1062
+ return segments;
1063
+ };
1064
+ var parseSegmentsFromList = (segmentList, baseUrl) => {
1065
+ const segmentUrls = segmentList.get("SegmentURL");
1066
+ const segments = [];
1067
+ for (const segmentUrl of segmentUrls) {
1068
+ let mediaUrl = segmentUrl.get("media");
1069
+ if (!mediaUrl) mediaUrl = baseUrl;
1070
+ else if (!mediaUrl.startsWith("https://"))
1071
+ mediaUrl = new URL(mediaUrl, baseUrl).toString();
1072
+ segments.push({ url: mediaUrl, range: segmentUrl.get("mediaRange") });
1073
+ }
1074
+ return segments;
1075
+ };
1076
+ var parseSegmentFromBase = async (segmentBase, baseUrl) => {
1077
+ const initialization = segmentBase.get("Initialization");
1078
+ let mediaRange = "";
1079
+ if (initialization) {
1080
+ }
1081
+ return { url: baseUrl, range: mediaRange };
1082
+ };
1083
+ var transformSegmentUrls = (segments) => {
1084
+ for (const segment of segments) {
1085
+ const hasHtmlEscapeCode = segment.url.includes("&amp;");
1086
+ if (hasHtmlEscapeCode) {
1087
+ const url = new URL(segment.url);
1088
+ const entries = new URLSearchParams(
1089
+ url.searchParams.toString()
1090
+ ).entries();
1091
+ for (const [key, value] of entries) {
1092
+ url.searchParams.delete(key);
1093
+ url.searchParams.append(key.replaceAll("amp;", ""), value);
1094
+ }
1095
+ segment.url = url.toString();
1096
+ }
1097
+ }
1098
+ };
1099
+ var protectionSchemas = {
1100
+ "urn:mpeg:dash:mp4protection:2011": "common",
1101
+ "urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95": "playready",
1102
+ "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed": "widevine"
1103
+ };
1104
+ var parseContentProtection = (contentProtections) => {
1105
+ const protection = {};
1106
+ for (const contentProtection of contentProtections) {
1107
+ const id = contentProtection.get("schemeIdUri")?.toLowerCase();
1108
+ const value = contentProtection.get("value");
1109
+ const pssh = contentProtection.get("cenc:pssh")?.get();
1110
+ const defaultKeyId = contentProtection.get("cenc:default_KID");
1111
+ const data = { id, value, pssh, defaultKeyId };
1112
+ protection[protectionSchemas[id]] = data;
1113
+ }
1114
+ return protection;
1115
+ };
1116
+ var parseManifest = async (text, url, fallbackLanguage) => {
1117
+ const mpd = appendUtils(xml.parse(text)).get("MPD");
1118
+ const period = mpd.get("Period");
1119
+ const durationString = period.get("duration") || mpd.get("mediaPresentationDuration");
1120
+ const duration = parseDuration(durationString);
1121
+ const videos = [];
1122
+ const audios = [];
1123
+ const subtitles = [];
1124
+ for (const adaptationSet of period.getAll("AdaptationSet")) {
1125
+ for (const representation of adaptationSet.getAll("Representation")) {
1126
+ const { get, getAll } = combineGetters(representation, adaptationSet);
1127
+ const { contentType, mimeType } = parseContentTypes(representation);
1128
+ const codecs = parseCodecs(representation, contentType, mimeType);
1129
+ const language = parseLanguage(
1130
+ representation,
1131
+ adaptationSet,
1132
+ fallbackLanguage
1133
+ );
1134
+ const baseUrl = parseBaseUrl(url, mpd, period, representation);
1135
+ const segmentTemplate = get("SegmentTemplate");
1136
+ const segmentList = get("SegmentList");
1137
+ const segmentBase = get("SegmentBase");
1138
+ const segments = [];
1139
+ if (segmentTemplate) {
1140
+ const segmentsFromTemplate = parseSegmentsFromTemplate(
1141
+ segmentTemplate,
1142
+ baseUrl,
1143
+ url,
1144
+ duration,
1145
+ representation
1146
+ );
1147
+ segments.push(...segmentsFromTemplate);
1148
+ } else if (segmentList) {
1149
+ const segmentsFromList = parseSegmentsFromList(segmentList, baseUrl);
1150
+ segments.push(...segmentsFromList);
1151
+ } else if (segmentBase) {
1152
+ const segmentFromBase = await parseSegmentFromBase(
1153
+ segmentBase,
1154
+ baseUrl
1155
+ );
1156
+ segments.push(segmentFromBase);
1157
+ } else if (baseUrl) {
1158
+ segments.push({ url: baseUrl });
1159
+ } else {
1160
+ throw new Error(
1161
+ "Could not find a way to get segments from this MPD manifest."
1162
+ );
1163
+ }
1164
+ transformSegmentUrls(segments);
1165
+ const label = get("label");
1166
+ const fps = get("frameRate") ?? segmentBase?.attributes.timescale;
1167
+ const width = get("width") ?? 0;
1168
+ const height = get("height") ?? 0;
1169
+ const bitrate = get("bandwidth");
1170
+ const supplementalProps = getAll("SupplementalProperty");
1171
+ const essentialProps = getAll("EssentialProperty");
1172
+ const accessibilities = adaptationSet.getAll("Accessibility");
1173
+ const roles = adaptationSet.getAll("Role");
1174
+ const contentProtections = getAll("ContentProtection");
1175
+ const id = [
1176
+ new URL(baseUrl).hostname,
1177
+ contentType,
1178
+ codecs,
1179
+ bitrate,
1180
+ language,
1181
+ mpd.get("id"),
1182
+ period.get("id"),
1183
+ get("id"),
1184
+ get("audioTrackId")
1185
+ ].filter(Boolean).join("-").replaceAll("/", "-");
1186
+ switch (contentType) {
1187
+ case "video": {
1188
+ const track = createVideoTrack({
1189
+ id,
1190
+ label,
1191
+ type: contentType,
1192
+ codec: parseVideoCodec(codecs),
1193
+ dynamicRange: parseDynamicRange(
1194
+ codecs,
1195
+ supplementalProps,
1196
+ essentialProps
1197
+ ),
1198
+ contentProtection: parseContentProtection(contentProtections),
1199
+ bitrate,
1200
+ duration,
1201
+ width,
1202
+ height,
1203
+ fps,
1204
+ language,
1205
+ segments
1206
+ });
1207
+ videos.push(track);
1208
+ break;
1209
+ }
1210
+ case "audio": {
1211
+ const track = createAudioTrack({
1212
+ id,
1213
+ label,
1214
+ type: contentType,
1215
+ codec: parseAudioCodec(codecs),
1216
+ channels: get("AudioChannelConfiguration")?.get("value"),
1217
+ jointObjectCoding: getDolbyDigitalPlusComplexityIndex(supplementalProps),
1218
+ isDescriptive: checkIsDescriptive(accessibilities),
1219
+ bitrate,
1220
+ duration,
1221
+ language,
1222
+ segments
1223
+ });
1224
+ audios.push(track);
1225
+ break;
1226
+ }
1227
+ case "text": {
1228
+ const track = createSubtitleTrack({
1229
+ id,
1230
+ label,
1231
+ type: contentType,
1232
+ codec: parseSubtitleCodec(codecs || "vtt"),
1233
+ isClosedCaption: checkIsClosedCaption(roles),
1234
+ isSdh: checkIsSdh(accessibilities),
1235
+ isForced: checkIsForced(roles),
1236
+ bitrate,
1237
+ duration,
1238
+ language,
1239
+ segments
1240
+ });
1241
+ subtitles.push(track);
1242
+ break;
1243
+ }
1244
+ case "image":
1245
+ break;
1246
+ default:
1247
+ throw new Error(`Unknown content type: ${contentType}`);
1248
+ }
1249
+ }
1250
+ }
1251
+ videos.sort((a, b) => b.bitrate.bps - a.bitrate.bps);
1252
+ return {
1253
+ duration,
1254
+ tracks: {
1255
+ all: videos.concat(audios).concat(subtitles),
1256
+ videos,
1257
+ audios,
1258
+ subtitles,
1259
+ withResolution: createResolutionFilter(videos),
1260
+ withVideoCodecs: createVideoCodecFilter(videos),
1261
+ withVideoQuality: createVideoQualityFilter(videos),
1262
+ withAudioCodecs: createAudioCodecFilter(audios),
1263
+ withAudioLanguages: createAudioLanguageFilter(audios),
1264
+ withAudioChannels: createAudioChannelsFilter(audios),
1265
+ withSubtitleLanguages: createSubtitleLanguageFilter(subtitles)
1266
+ }
1267
+ };
1268
+ };
1269
+ module2.exports = { parseManifest };
1270
+ }
1271
+ });
1272
+
1273
+ // lib/hls.js
1274
+ var require_hls = __commonJS({
1275
+ "lib/hls.js"(exports2, module2) {
1276
+ "use strict";
1277
+ var { dirname, basename } = require("path");
1278
+ var m3u8Parser = require("m3u8-parser");
1279
+ var { parseBitrate, getQualityLabel } = require_util();
1280
+ var {
1281
+ createResolutionFilter,
1282
+ createVideoQualityFilter,
1283
+ createAudioLanguageFilter,
1284
+ createSubtitleLanguageFilter,
1285
+ createVideoCodecFilter,
1286
+ createAudioCodecFilter,
1287
+ createAudioChannelsFilter
1288
+ } = require_track();
1289
+ var { createAudioTrack } = require_audio();
1290
+ var { createVideoTrack } = require_video();
1291
+ var parseM3u8 = (manifestString) => {
1292
+ const parser = new m3u8Parser.Parser();
1293
+ parser.push(manifestString);
1294
+ parser.end();
1295
+ return parser.manifest;
1296
+ };
1297
+ var fetchPlaylist = async (url) => {
1298
+ const response = await fetch(url);
1299
+ if (!response.ok)
1300
+ throw new Error(`Failed to fetch playlist (${response.status}): ${url}`);
1301
+ const text = await response.text();
1302
+ return parseM3u8(text);
1303
+ };
1304
+ var parseUrl = (playlistUri, manifestUri) => {
1305
+ let value = playlistUri;
1306
+ if (!value.startsWith("https://"))
1307
+ value = new URL(value, manifestUri).toString() + new URL(manifestUri).search;
1308
+ return value;
1309
+ };
1310
+ var urlsSame = (url1, url2) => {
1311
+ return new URL(url1).pathname === new URL(url2).pathname;
1312
+ };
1313
+ var parseMediaGroup = (groups, manifestUri) => {
1314
+ const results = [];
1315
+ if (!groups) return results;
1316
+ for (const [groupId, group] of Object.entries(groups)) {
1317
+ for (const [label, entity] of Object.entries(group)) {
1318
+ const url = parseUrl(entity.uri, manifestUri);
1319
+ const existing = results.find((result) => urlsSame(result.url, url));
1320
+ if (!existing)
1321
+ results.push({
1322
+ groupId,
1323
+ id: entity.uri.replace("/", ""),
1324
+ type: groupId,
1325
+ label,
1326
+ language: entity.language,
1327
+ url,
1328
+ default: entity.default
1329
+ });
1330
+ }
1331
+ }
1332
+ return results;
1333
+ };
1334
+ var getAudioPlaylists = (m3u8, manifestUri) => {
1335
+ if (!m3u8.mediaGroups) return [];
1336
+ return parseMediaGroup(m3u8.mediaGroups.AUDIO, manifestUri);
1337
+ };
1338
+ var getSubtitlePlaylists = (m3u8, manifestUri) => {
1339
+ if (!m3u8.mediaGroups) return [];
1340
+ return parseMediaGroup(m3u8.mediaGroups.SUBTITLES, manifestUri);
1341
+ };
1342
+ var getVideoPlaylists = (m3u8, manifestUri) => {
1343
+ if (!m3u8.playlists) return [];
1344
+ return m3u8.playlists.map((data) => {
1345
+ const bandwidth = data.attributes?.BANDWIDTH;
1346
+ const url = data.resolvedUri || parseUrl(data.uri, manifestUri);
1347
+ const track = {
1348
+ id: data.uri.replace("/", ""),
1349
+ bitrate: parseBitrate(bandwidth),
1350
+ url
1351
+ };
1352
+ track.type = "video";
1353
+ if (data.attributes.RESOLUTION) {
1354
+ track.resolution = data.attributes.RESOLUTION;
1355
+ track.quality = getQualityLabel(track.resolution);
1356
+ }
1357
+ if (data.attributes["VIDEO-RANGE"])
1358
+ track.dynamicRange = data.attributes["VIDEO-RANGE"];
1359
+ if (data.attributes.CODECS) track.codecs = data.attributes.CODECS;
1360
+ if (data.attributes["FRAME-RATE"])
1361
+ track.frameRate = data.attributes["FRAME-RATE"];
1362
+ return track;
1363
+ });
1364
+ };
1365
+ var segmentsDto = (data = [], track) => {
1366
+ const mapSegment = (item) => {
1367
+ let url = item.resolvedUri || item.uri;
1368
+ if (!url.startsWith("https://") && track.url) {
1369
+ const baseUrl = dirname(track.url) + "/";
1370
+ url = new URL(url, baseUrl).toString();
1371
+ }
1372
+ return {
1373
+ url,
1374
+ duration: item.duration,
1375
+ number: item.number,
1376
+ presentationTime: item.presentationTime
1377
+ };
1378
+ };
1379
+ const segments = data.map(mapSegment);
1380
+ const init = data[0].map;
1381
+ if (data.length && (init?.resolvedUri || init?.uri)) {
1382
+ const url = init?.resolvedUri || parseUrl(init.uri, track.url);
1383
+ segments.unshift({
1384
+ url,
1385
+ init: true,
1386
+ duration: 0,
1387
+ number: 0,
1388
+ presentationTime: 0
1389
+ });
1390
+ }
1391
+ return segments;
1392
+ };
1393
+ var parseSegments = (playlist, track) => {
1394
+ track.segments = segmentsDto(playlist.segments, track);
1395
+ if (playlist.contentProtection) {
1396
+ track.protection = {};
1397
+ const fairplayLegacy = playlist.contentProtection["com.apple.fps.1_0"];
1398
+ if (fairplayLegacy)
1399
+ track.protection.fairplay = {
1400
+ keyFormat: fairplayLegacy.attributes.KEYFORMAT,
1401
+ uri: fairplayLegacy.attributes.URI,
1402
+ method: fairplayLegacy.attributes.METHOD
1403
+ };
1404
+ const widevine = playlist.contentProtection["com.widevine.alpha"];
1405
+ if (widevine) {
1406
+ track.protection.widevine = {
1407
+ pssh: widevine.pssh,
1408
+ uri: widevine.attributes.schemeIdUri,
1409
+ keyId: widevine.attributes.keyId
1410
+ };
1411
+ }
1412
+ }
1413
+ };
1414
+ var fetchTrackSegments = (tracks) => {
1415
+ return Promise.all(
1416
+ tracks.map(async (track) => {
1417
+ const playlist = await fetchPlaylist(track.url);
1418
+ parseSegments(playlist, track);
1419
+ })
1420
+ );
1421
+ };
1422
+ var parseManifest = async (manifestString, manifestUri) => {
1423
+ const m3u8 = parseM3u8(manifestString);
1424
+ const videos = getVideoPlaylists(m3u8, manifestUri);
1425
+ const audios = getAudioPlaylists(m3u8, manifestUri);
1426
+ const subtitles = getSubtitlePlaylists(m3u8, manifestUri);
1427
+ if (!m3u8.playlists && m3u8.segments) {
1428
+ const { pathname } = new URL(manifestUri);
1429
+ const isAudio = pathname.includes(".m4a") || pathname.includes(".mp3") || pathname.includes(".opus");
1430
+ if (isAudio) {
1431
+ const track = createAudioTrack({
1432
+ id: "audio" + basename(pathname),
1433
+ label: "audio",
1434
+ type: "audio",
1435
+ codec: "",
1436
+ channels: 2,
1437
+ jointObjectCoding: "",
1438
+ isDescriptive: false,
1439
+ bitrate: NaN,
1440
+ duration: NaN,
1441
+ language: ""
1442
+ });
1443
+ parseSegments(m3u8, track);
1444
+ audios.push(track);
1445
+ } else {
1446
+ const track = createVideoTrack({
1447
+ id: "video" + basename(pathname),
1448
+ label: "video",
1449
+ type: "video",
1450
+ codec: "",
1451
+ dynamicRange: "",
1452
+ contentProtection: "",
1453
+ bitrate: NaN,
1454
+ duration: NaN,
1455
+ width: NaN,
1456
+ height: NaN,
1457
+ fps: NaN,
1458
+ language: ""
1459
+ });
1460
+ parseSegments(m3u8, track);
1461
+ videos.push(track);
1462
+ }
1463
+ } else {
1464
+ await Promise.all([
1465
+ fetchTrackSegments(videos),
1466
+ fetchTrackSegments(audios),
1467
+ fetchTrackSegments(subtitles)
1468
+ ]);
1469
+ }
1470
+ const manifest = {
1471
+ tracks: {
1472
+ all: videos.concat(audios).concat(subtitles),
1473
+ videos,
1474
+ audios,
1475
+ subtitles,
1476
+ withResolution: createResolutionFilter(videos),
1477
+ withVideoCodecs: createVideoCodecFilter(videos),
1478
+ withVideoQuality: createVideoQualityFilter(videos),
1479
+ withAudioCodecs: createAudioCodecFilter(audios),
1480
+ withAudioLanguages: createAudioLanguageFilter(audios),
1481
+ withAudioChannels: createAudioChannelsFilter(audios),
1482
+ withSubtitleLanguages: createSubtitleLanguageFilter(subtitles)
1483
+ }
1484
+ };
1485
+ return manifest;
1486
+ };
1487
+ module2.exports = { parseManifest };
1488
+ }
1489
+ });
1490
+
1491
+ // dasha.js
1492
+ var dash = require_dash();
1493
+ var hls = require_hls();
1494
+ var {
1495
+ filterByResolution,
1496
+ filterByQuality,
1497
+ filterByCodecs,
1498
+ filterByLanguages,
1499
+ filterByChannels
1500
+ } = require_track();
1501
+ var parse = (text, url, fallbackLanguage) => {
1502
+ if (text.includes("<MPD"))
1503
+ return dash.parseManifest(text, url, fallbackLanguage);
1504
+ else if (text.includes("#EXTM3U")) return hls.parseManifest(text, url);
1505
+ else throw new Error("Invalid manifest");
1506
+ };
1507
+ module.exports = {
1508
+ parse,
1509
+ filterByResolution,
1510
+ filterByQuality,
1511
+ filterByCodecs,
1512
+ filterByLanguages,
1513
+ filterByChannels
1514
+ };