@dolby-optiview/ads-sdk-adapter-hlsjs 1.2.1 → 1.4.0
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/HlsJsAdapter.d.ts +4 -1
- package/dist/HlsJsAdapter.js +1 -1
- package/package.json +2 -2
package/dist/HlsJsAdapter.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Hls from 'hls.js';
|
|
2
|
-
import type { PlayerAdapter, PlayerAdapterEvent, PlayerAdapterEventHandler, VideoQuality } from '@dolby-optiview/ads-sdk-core';
|
|
2
|
+
import type { ExternalPlaybackState, PlayerAdapter, PlayerAdapterEvent, PlayerAdapterEventHandler, VideoQuality } from '@dolby-optiview/ads-sdk-core';
|
|
3
3
|
/**
|
|
4
4
|
* The {@link PlayerAdapter} for HLS.js, from the `@dolby-optiview/ads-sdk-adapter-hlsjs` package
|
|
5
5
|
* (peer dependency: `hls.js` 1.x).
|
|
@@ -30,6 +30,7 @@ import type { PlayerAdapter, PlayerAdapterEvent, PlayerAdapterEventHandler, Vide
|
|
|
30
30
|
export declare class HlsJsAdapter implements PlayerAdapter {
|
|
31
31
|
private hls;
|
|
32
32
|
private video;
|
|
33
|
+
private externalPlayback;
|
|
33
34
|
private eventListeners;
|
|
34
35
|
private boundHandlers;
|
|
35
36
|
private _programDateTime;
|
|
@@ -224,6 +225,8 @@ export declare class HlsJsAdapter implements PlayerAdapter {
|
|
|
224
225
|
* Unsubscribe from player events.
|
|
225
226
|
*/
|
|
226
227
|
off(event: PlayerAdapterEvent, handler: PlayerAdapterEventHandler): void;
|
|
228
|
+
get externalPlaybackState(): ExternalPlaybackState | undefined;
|
|
229
|
+
setExternalPlaybackAllowed(allowed: boolean): void;
|
|
227
230
|
/**
|
|
228
231
|
* Clean up resources.
|
|
229
232
|
*/
|
package/dist/HlsJsAdapter.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"hls.js";import{decodeUtf8 as t,parseId3GeobFrames as s}from"@dolby-optiview/ads-sdk-core/id3";import{
|
|
1
|
+
import e from"hls.js";import{decodeUtf8 as t,parseId3GeobFrames as s}from"@dolby-optiview/ads-sdk-core/id3";import{observeExternalPlayback as i,setExternalPlaybackAllowed as r}from"@dolby-optiview/ads-sdk-core/external-playback";import{HlsMediaError as n}from"./hlsErrorToMediaError";export class HlsJsAdapter{constructor(e,t){this.eventListeners=new Map,this.boundHandlers=new Map,this._programDateTime=null,this.deferredSeekTime=null,this.endedEmitted=!1,this.activeOperation=null,this.levelBeforePin=null,this.parsedCues=new Map,this.presentedPts=new Set,this.id3TrackListener=null,this.hls=e,this.video=t,this.externalPlayback=i(t,e=>this.emit("externalplaybackchange",e)),this.setupHlsListeners(),this.setupVideoListeners()}get currentTime(){return this.video.currentTime}get duration(){return this.video.duration}get isLive(){const e=this.hls?.latestLevelDetails;return"boolean"==typeof e?.live?e.live:null}get paused(){return this.video.paused}get playbackReady(){return this.video.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&!this.video.seeking}get muted(){return this.video.muted}set muted(e){this.video.muted=e}get volume(){return this.video.volume}set volume(e){this.video.volume=e}get playbackRate(){return this.video.playbackRate}set playbackRate(e){this.video.playbackRate=e}get videoElement(){return this.video}get supportsParallelBuffering(){return e.isSupported()}get programDateTime(){return this._programDateTime}pause(){this.video.pause()}async play(){await this.video.play()}seek(e){this.video.seeking?this.deferredSeekTime=e:this.video.currentTime=e}get sourceUrl(){return this.hls.url??null}async load(t){this.endedEmitted=!1;const s=this.beginOperation();return new Promise((i,r)=>{const a=()=>{this.hls.off(e.Events.MANIFEST_PARSED,a),this.hls.off(e.Events.ERROR,o),this.endOperation(s),i()},o=(t,i)=>{i.fatal&&(this.hls.off(e.Events.MANIFEST_PARSED,a),this.hls.off(e.Events.ERROR,o),this.endOperation(s),r(new n("HLS load error",i)))};this.hls.on(e.Events.MANIFEST_PARSED,a),this.hls.on(e.Events.ERROR,o),this.hls.loadSource(t),this.hls.attachMedia(this.video)})}unload(){this.deferredSeekTime=null,this.activeOperation=null,this.hls.stopLoad(),this.hls.detachMedia()}recreateMediaPipeline(t){this.deferredSeekTime=null;const s=this.beginOperation();return new Promise((i,r)=>{const a=()=>{this.video.removeEventListener("loadedmetadata",o),this.hls.off(e.Events.FRAG_BUFFERED,h),this.hls.off(e.Events.ERROR,l),this.endOperation(s)},o=()=>{d()},h=()=>{d()},d=()=>{Math.abs(this.video.currentTime-t.startTime)>.5&&(this.video.currentTime=t.startTime),a(),i()},l=(e,t)=>{t.fatal&&(a(),r(new n("HLS pipeline recreate error",t)))};this.video.addEventListener("loadedmetadata",o),this.hls.on(e.Events.FRAG_BUFFERED,h),this.hls.on(e.Events.ERROR,l),this.hls.detachMedia(),this.hls.attachMedia(this.video);try{this.video.currentTime=t.startTime}catch{}this.hls.startLoad(t.startTime)})}async preload(t){if(e.isSupported())return new Promise(s=>{const i=new e({startFragPrefetch:!0,autoStartLoad:!0});let r=!1;const n=()=>{if(!r){r=!0,clearTimeout(h),i.off(e.Events.FRAG_LOADED,a),i.off(e.Events.ERROR,o);try{i.destroy()}catch{}s()}},a=()=>n(),o=(e,t)=>{t.fatal&&n()},h=setTimeout(n,8e3);i.on(e.Events.FRAG_LOADED,a),i.on(e.Events.ERROR,o),i.loadSource(t)})}get maxLiveSeekPosition(){const e=this.hls.latestLevelDetails;if(!e?.live)return null;const t=this.hls.liveSyncPosition;return"number"==typeof t&&Number.isFinite(t)?t:null}get targetDuration(){const e=this.hls.latestLevelDetails,t=e?.targetduration;return e?.live&&"number"==typeof t&&Number.isFinite(t)&&t>0?t:null}requestLiveStartOffset(e,t){const s=e;if(null===s||!Number.isFinite(s)||s<=0)return!1;if(this.hls.latestLevelDetails)return!1;const i=this.hls.config;return!(void 0===i.liveMaxLatencyDuration&&i.liveMaxLatencyDurationCount<=s)&&(delete i.liveSyncDuration,i.liveSyncDurationCount=s,this.hls.userConfig.liveSyncDurationCount=s,!0)}setVideoQuality(e){if(null===e){if(null===this.levelBeforePin)return!1;const e=this.levelBeforePin;try{return this.hls.nextLevel=e,this.hls.nextLevel!==e?!1:(this.levelBeforePin=null,!0)}catch{return!1}}const t=this.hls.levels;if(!t||t.length<2)return!1;let s=0;for(let e=1;e<t.length;e++)t[e].bitrate<t[s].bitrate&&(s=e);const i=t[s].bitrate;if("number"!=typeof i||!Number.isFinite(i)||i<=0)return!1;const r=null===this.levelBeforePin;let n;r&&(this.levelBeforePin=this.hls.manualLevel);try{this.hls.nextLevel=s,n=this.hls.nextLevel===s}catch{n=!1}return!!n||(r&&(this.levelBeforePin=null),!1)}on(e,t){this.eventListeners.has(e)||this.eventListeners.set(e,new Set),this.eventListeners.get(e).add(t)}off(e,t){const s=this.eventListeners.get(e);s&&s.delete(t)}get externalPlaybackState(){return this.externalPlayback?.state}setExternalPlaybackAllowed(e){r(this.video,e)}destroy(){this.externalPlayback?.dispose();for(const[e,t]of this.boundHandlers)this.video.removeEventListener(e,t);this.boundHandlers.clear(),this.eventListeners.clear(),this.deferredSeekTime=null,this.id3TrackListener&&(this.id3TrackListener.track.removeEventListener("cuechange",this.id3TrackListener.handler),this.id3TrackListener=null),this.parsedCues.clear(),this.presentedPts.clear()}beginOperation(){const e=Symbol("hls-operation");return this.activeOperation=e,e}endOperation(e){this.activeOperation===e&&(this.activeOperation=null)}setupHlsListeners(){this.hls.on(e.Events.ERROR,(e,t)=>{t.fatal&&null===this.activeOperation&&this.emit("error",new n("HLS playback error",t))}),this.hls.on(e.Events.MEDIA_ENDED,()=>{this.emitEndedOnce()}),this.hls.on(e.Events.FRAG_CHANGED,(e,t)=>{t.frag.programDateTime&&this.anchorProgramDateTime(t.frag.programDateTime,t.frag.start)}),this.hls.on(e.Events.LEVEL_LOADED,(e,t)=>{if(t.details.hasProgramDateTime&&t.details.fragments.length>0){const e=t.details.fragments[0];e.programDateTime&&this.anchorProgramDateTime(e.programDateTime,e.start)}}),this.hls.on(e.Events.FRAG_PARSING_METADATA,(e,i)=>{for(const e of i.samples??[]){const i=s(e.data);if(0===i.length){const t={type:"id3",startTime:e.pts,raw:e.data,phase:"parsed"};this.emit("timedmetadata",t);continue}const r=[];for(const s of i){const i={type:"id3",startTime:e.pts,description:s.description,mimeType:s.mimeType,messageData:t(s.data),raw:e.data,phase:"parsed"};r.push(i),this.emit("timedmetadata",i)}this.parsedCues.set(e.pts,r),this.pruneParsedCues()}this.attachId3CueEnterListener()})}attachId3CueEnterListener(){if(this.id3TrackListener)return;const e=this.video.textTracks;if(!e)return;let t;for(let s=0;s<e.length;s++){const i=e[s];if("metadata"===i.kind&&"id3"===i.label){t=i;break}}if(!t||"function"!=typeof t.addEventListener)return;"disabled"===t.mode&&(t.mode="hidden");const s=()=>{const e=t?.activeCues;if(e)for(let t=0;t<e.length;t++){const s=e[t].startTime;if(this.presentedPts.has(s))continue;const i=this.parsedCues.get(s);if(i){this.presentedPts.add(s);for(const e of i)this.emit("timedmetadata",{...e,phase:"presented"})}}};t.addEventListener("cuechange",s),this.id3TrackListener={track:t,handler:s}}pruneParsedCues(){const e=this.video.currentTime-120;for(const t of this.parsedCues.keys())t<e&&(this.parsedCues.delete(t),this.presentedPts.delete(t))}setupVideoListeners(){const e=()=>{this.updateProgramDateTime(),this.emit("timeupdate")},t=()=>{this.emitEndedOnce()},s=()=>{this.emit("error",this.video.error)},i=()=>{if(this.emit("seeked"),null!==this.deferredSeekTime){const e=this.deferredSeekTime;this.deferredSeekTime=null,this.seek(e)}},r=()=>{this.emit("volumechange")},n=()=>{this.emit("waiting")},a=()=>{this.endedEmitted=!1,this.emit("playing")},o=()=>{this.emit("pause")};this.video.addEventListener("timeupdate",e),this.video.addEventListener("ended",t),this.video.addEventListener("error",s),this.video.addEventListener("seeked",i),this.video.addEventListener("volumechange",r),this.video.addEventListener("waiting",n),this.video.addEventListener("playing",a),this.video.addEventListener("pause",o),this.boundHandlers.set("timeupdate",e),this.boundHandlers.set("ended",t),this.boundHandlers.set("error",s),this.boundHandlers.set("seeked",i),this.boundHandlers.set("volumechange",r),this.boundHandlers.set("waiting",n),this.boundHandlers.set("playing",a),this.boundHandlers.set("pause",o)}emitEndedOnce(){this.endedEmitted||(this.endedEmitted=!0,this.emit("ended"))}updateProgramDateTime(){const e=this.hls.levels,t=this.hls.currentLevel;if(t>=0&&e[t]?.details){const s=e[t].details;if(s?.hasProgramDateTime&&s.fragments.length>0){const e=s.fragments[0];e.programDateTime&&this.anchorProgramDateTime(e.programDateTime,e.start)}}}anchorProgramDateTime(e,t){this._programDateTime=new Date(e+1e3*(this.video.currentTime-t))}emit(e,t){const s=this.eventListeners.get(e);if(s)for(const e of s)try{e(t)}catch(e){console.error("[HlsJsAdapter] Event handler error:",e)}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dolby-optiview/ads-sdk-adapter-hlsjs",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "HLS.js adapter for OptiView Ads SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"sideEffects": false,
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@dolby-optiview/ads-sdk-core": "^1.
|
|
41
|
+
"@dolby-optiview/ads-sdk-core": "^1.4.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"hls.js": "^1.0.0"
|