@mango-iiif/av 0.0.1 → 0.0.3
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/README.md +6 -0
- package/dist/annotations.d.ts +2 -2
- package/dist/annotations.js +3 -3
- package/dist/chapters.d.ts +2 -2
- package/dist/chapters.js +3 -3
- package/dist/chunk-6JIJRMNE.js +218 -0
- package/dist/chunk-6JIJRMNE.js.map +1 -0
- package/dist/{chunk-3LLEY7MA.js → chunk-AZFOTEAO.js} +2 -2
- package/dist/{chunk-GX7UU6V4.js → chunk-CSE4GIHB.js} +61 -21
- package/dist/chunk-CSE4GIHB.js.map +1 -0
- package/dist/{chunk-ML77YRJL.js → chunk-D7W5UINF.js} +92 -18
- package/dist/chunk-D7W5UINF.js.map +1 -0
- package/dist/{chunk-R4OUWZ3R.js → chunk-EV6YN7WV.js} +22 -8
- package/dist/chunk-EV6YN7WV.js.map +1 -0
- package/dist/{chunk-JXUHKKIX.js → chunk-HM72GHCH.js} +2 -2
- package/dist/{chunk-IFTSCRCU.js → chunk-NH6PEDNF.js} +3 -3
- package/dist/{chunk-PZ6GV6ZJ.js → chunk-RP47ZLOD.js} +6 -6
- package/dist/{chunk-YH6DS7J6.js → chunk-U3H552X2.js} +5 -4
- package/dist/chunk-U3H552X2.js.map +1 -0
- package/dist/{controller-DLy38ais.d.ts → controller-BLA8XNsG.d.ts} +10 -2
- package/dist/{controller-element-BOKM9v2S.d.ts → controller-element-BY0157ve.d.ts} +1 -1
- package/dist/core.d.ts +2 -2
- package/dist/core.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +9 -9
- package/dist/media.d.ts +1 -1
- package/dist/media.js +4 -4
- package/dist/player.d.ts +3 -2
- package/dist/player.js +5 -4
- package/dist/player.js.map +1 -1
- package/dist/transcript-element.d.ts +2 -2
- package/dist/transcript-element.js +4 -4
- package/docs/API.md +10 -0
- package/package.json +1 -1
- package/dist/chunk-GX7UU6V4.js.map +0 -1
- package/dist/chunk-ML77YRJL.js.map +0 -1
- package/dist/chunk-NTHMZZYJ.js +0 -38
- package/dist/chunk-NTHMZZYJ.js.map +0 -1
- package/dist/chunk-R4OUWZ3R.js.map +0 -1
- package/dist/chunk-YH6DS7J6.js.map +0 -1
- /package/dist/{chunk-3LLEY7MA.js.map → chunk-AZFOTEAO.js.map} +0 -0
- /package/dist/{chunk-JXUHKKIX.js.map → chunk-HM72GHCH.js.map} +0 -0
- /package/dist/{chunk-IFTSCRCU.js.map → chunk-NH6PEDNF.js.map} +0 -0
- /package/dist/{chunk-PZ6GV6ZJ.js.map → chunk-RP47ZLOD.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/mango-av-media.ts"],"sourcesContent":["import { AVPlayerController } from '../controller';\nimport { loadTranscript } from '../transcript';\nimport { ensureMediaChrome } from './media-chrome';\nimport { playFromInteraction } from './playback';\nimport { AudioArtVisualizer, audioArtContentHtml, audioArtTranscriptHtml, resolveAudioVisualizerMode, syncAudioArtTranscript } from './audio-art';\nimport type {\n AVAnnotation,\n AVCanvas,\n AVManifest,\n AVPlayerConfig,\n AVPlayerEventMap,\n AVStrings,\n Chapter,\n JsonObject,\n MetadataEntry,\n TranscriptCue,\n} from '../types';\nimport { escapeHtml, formatString, formatTime, resolveStrings } from '../utils';\n\nconst HTMLElementBase = (globalThis.HTMLElement ?? class {}) as typeof HTMLElement;\n\nlet hlsElementRegistration: Promise<unknown> | undefined;\nconst ensureHlsElement = (): Promise<unknown> => {\n hlsElementRegistration ??= import('hls-video-element');\n return hlsElementRegistration;\n};\n\nconst eventTypes: Array<keyof AVPlayerEventMap> = [\n 'av-loadstart',\n 'av-ready',\n 'av-error',\n 'av-canvaschange',\n 'av-sourcechange',\n 'av-play',\n 'av-pause',\n 'av-timeupdate',\n 'av-seek',\n 'av-ended',\n 'av-annotationschange',\n 'av-configchange',\n 'av-statechange',\n];\n\nconst styles = `\n :host {\n --mango-av-accent: #5b3fd6;\n --mango-av-accent-contrast: #fff;\n --mango-av-background: #fff;\n --mango-av-surface: #f5f5f8;\n --mango-av-text: #18181b;\n --mango-av-muted: #62626a;\n --mango-av-border: #d7d7de;\n --mango-av-radius: .65rem;\n --mango-av-font: ui-sans-serif, system-ui, sans-serif;\n --mango-av-panel-width: 24rem;\n --mango-av-player-aspect-ratio: 16 / 9;\n --media-primary-color: var(--mango-av-accent-contrast);\n --media-secondary-color: var(--mango-av-accent);\n color: var(--mango-av-text);\n display: block;\n font-family: var(--mango-av-font);\n }\n *, *::before, *::after { box-sizing: border-box; }\n button, input, select { font: inherit; }\n button, select { cursor: pointer; }\n .shell { background: var(--mango-av-background); border: 1px solid var(--mango-av-border); border-radius: var(--mango-av-radius); overflow: clip; }\n .header { padding: 1rem 1.1rem; }\n .header h2 { font-size: 1.15rem; margin: 0; }\n .header p { color: var(--mango-av-muted); margin: .35rem 0 0; }\n .layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(18rem, var(--mango-av-panel-width)); }\n .player-column { align-self: start; background: #08080a; min-width: 0; position: relative; }\n media-controller { display: block; width: 100%; }\n media-controller:not([audio]) { aspect-ratio: var(--mango-av-player-aspect-ratio); }\n video, hls-video { display: block; height: 100%; object-fit: contain; width: 100%; }\n audio { width: 100%; }\n media-control-bar { width: 100%; }\n .audio-art { --mango-av-wave-edge-strength: 0%; --mango-av-wave-mid-strength: 0%; --mango-av-wave-rise: 8%; --mango-av-wave-strength: 0%; align-items: center; aspect-ratio: 16 / 7; background: linear-gradient(#09080d, #111019); color: white; display: flex; justify-content: center; overflow: hidden; padding: 2rem; position: relative; text-align: center; }\n .audio-art.visualizer--pulse { background: radial-gradient(ellipse 140% 72% at 50% calc(100% + var(--mango-av-wave-rise)), color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-strength), transparent) 0%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-mid-strength), transparent) 40%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-edge-strength), transparent) 62%, transparent 78%), linear-gradient(#09080d, #111019); }\n .audio-art-text { display: contents; }\n .audio-art-visualizer-canvas { height: 100%; inset: 0; pointer-events: none; position: absolute; width: 100%; }\n .audio-art img { height: 100%; inset: 0; object-fit: contain; position: absolute; width: 100%; }\n .audio-art-title { font-size: clamp(1.1rem, 3vw, 2rem); font-weight: 700; position: relative; z-index: 1; }\n .audio-art-transcript { height: 100%; inset: 0; overflow: hidden; position: absolute; z-index: 1; }\n .audio-art-cue { align-items: center; display: flex; flex-direction: column; font-size: clamp(.7rem, 1.3vw, .875rem); font-weight: 550; gap: .15rem; left: 12%; line-height: 1.35; position: absolute; right: 12%; top: 50%; transition: opacity 360ms ease, transform 480ms cubic-bezier(.22, 1, .36, 1); }\n .audio-art-transcript.seeking .audio-art-cue { transition: none; }\n .audio-art-cue.active { font-size: clamp(.78rem, 1.5vw, 1rem); font-weight: 650; }\n .audio-art-cue > span:last-child { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }\n .audio-art-speaker { font-size: .7em; letter-spacing: .04em; text-transform: uppercase; }\n .player-toolbar { align-items: center; background: #151518; color: #fff; display: flex; flex-wrap: wrap; gap: .5rem; justify-content: space-between; padding: .55rem .7rem; }\n .player-toolbar button, .player-toolbar select { background: #29292e; border: 1px solid #44444a; border-radius: .35rem; color: white; padding: .4rem .55rem; }\n .player-toolbar .group { align-items: center; display: flex; gap: .45rem; }\n .search-markers { background: #242429; height: .45rem; position: relative; }\n .search-marker { background: #ffe24a; border: 0; border-radius: 50%; height: .7rem; padding: 0; position: absolute; top: 50%; transform: translate(-50%, -50%); width: .7rem; }\n .resume { align-items: center; background: #fff8d7; color: #312900; display: flex; gap: .5rem; justify-content: center; padding: .6rem; }\n .resume button { background: var(--mango-av-accent); border: 0; border-radius: .35rem; color: var(--mango-av-accent-contrast); padding: .35rem .65rem; }\n .panel { border-left: 1px solid var(--mango-av-border); display: flex; flex-direction: column; min-height: 22rem; min-width: 0; }\n .tabs { background: var(--mango-av-surface); display: flex; gap: .1rem; overflow-x: auto; padding: .35rem; }\n .tab { background: transparent; border: 0; border-bottom: 3px solid transparent; color: var(--mango-av-muted); padding: .55rem .6rem; white-space: nowrap; }\n .tab[aria-selected=true] { border-color: var(--mango-av-accent); color: var(--mango-av-text); font-weight: 650; }\n .panel-content { flex: 1; max-height: 34rem; overflow: auto; padding: .85rem; }\n .empty { color: var(--mango-av-muted); font-style: italic; }\n .chapter-list, .annotation-list, .cue-list, .file-list { list-style: none; margin: 0; padding: 0; }\n .chapter-list .chapter-list { border-left: 1px solid var(--mango-av-border); margin-left: .8rem; padding-left: .55rem; }\n .chapter { margin-block: .3rem; }\n .chapter button, .annotation button, .cue button { background: transparent; border: 0; border-radius: .35rem; color: inherit; display: grid; gap: .15rem; padding: .5rem; text-align: left; width: 100%; }\n .chapter button { border-radius: 0; }\n .chapter button:hover, .annotation button:hover, .cue button:hover { background: var(--mango-av-surface); }\n .chapter button.active, .annotation button.active, .cue button.active { background: color-mix(in srgb, var(--mango-av-accent) 14%, transparent); box-shadow: inset 3px 0 var(--mango-av-accent); }\n .time { color: var(--mango-av-muted); font-size: .78rem; }\n .panel-tools { display: flex; flex-wrap: wrap; gap: .45rem; margin-bottom: .75rem; }\n .panel-tools input, .panel-tools select { border: 1px solid var(--mango-av-border); border-radius: .35rem; min-width: 0; padding: .45rem; }\n .panel-tools input { flex: 1; }\n .panel-tools a { align-content: center; color: var(--mango-av-accent); }\n .cue mark { background: #ffe770; }\n .speaker { font-weight: 700; }\n .tags { display: flex; flex-wrap: wrap; gap: .25rem; }\n .tag { background: var(--mango-av-surface); border-radius: 999px; font-size: .75rem; padding: .15rem .45rem; }\n dl { margin: 0; }\n dt { font-weight: 700; margin-top: .75rem; }\n dd { color: var(--mango-av-muted); margin: .2rem 0 0; }\n .file-list li { border-bottom: 1px solid var(--mango-av-border); padding: .55rem 0; }\n a { color: var(--mango-av-accent); }\n .error { background: #fff0f0; color: #8a1717; padding: 1rem; }\n .sr-only { clip: rect(0,0,0,0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; }\n @media (max-width: 760px) {\n .layout { grid-template-columns: 1fr; }\n .panel { border-left: 0; border-top: 1px solid var(--mango-av-border); }\n }\n`;\n\nconst metadataHtml = (entries: MetadataEntry[], ui: AVStrings): string => {\n if (entries.length === 0) return `<p class=\"empty\">${escapeHtml(ui.noMetadata)}</p>`;\n return `<dl>${entries.map((entry) => `\n <dt>${escapeHtml(entry.label)}</dt>\n <dd>${entry.values.map((value) => escapeHtml(value.value)).join('<br>')}</dd>\n `).join('')}</dl>`;\n};\n\nconst chapterHtml = (chapters: Chapter[], canvasId: string, ui: AVStrings, level = 1): string => {\n if (chapters.length === 0 && level === 1) return `<p class=\"empty\">${escapeHtml(ui.noChapters)}</p>`;\n return `<ul class=\"chapter-list\">${chapters.map((chapter) => {\n const active = chapter.canvasId === canvasId;\n const target = chapter.canvasId ? `data-canvas=\"${escapeHtml(chapter.canvasId)}\"` : '';\n const time = chapter.time ? `data-time=\"${chapter.time.start}\"` : '';\n return `<li class=\"chapter\">\n <button type=\"button\" class=\"${active ? 'active' : ''}\" ${target} ${time} ${chapter.canvasId ? '' : 'disabled'}>\n <span>${escapeHtml(chapter.label)}</span>\n ${chapter.time ? `<span class=\"time\">${formatTime(chapter.time.start)}</span>` : ''}\n </button>\n ${chapterHtml(chapter.children, canvasId, ui, level + 1)}\n </li>`;\n }).join('')}</ul>`;\n};\n\nconst highlight = (text: string, query: string): string => {\n const escaped = escapeHtml(text);\n if (!query) return escaped;\n const safeQuery = query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return escaped.replace(new RegExp(`(${safeQuery})`, 'gi'), '<mark>$1</mark>');\n};\n\nexport class MangoAVMediaElement extends HTMLElementBase {\n static observedAttributes = ['manifest-url', 'config'];\n\n readonly player: AVPlayerController;\n #root: ShadowRoot;\n #inputManifest: JsonObject | string | undefined;\n #config: AVPlayerConfig = {};\n #activePanel: NonNullable<AVPlayerConfig['activePanel']> = 'chapters';\n #transcriptCues: TranscriptCue[] = [];\n #transcriptIndex = 0;\n #transcriptQuery = '';\n #resumeTime: number | undefined;\n #loadingToken = 0;\n #resolvedSourceUrl: string | undefined;\n #sourceToken = 0;\n #visualizer = new AudioArtVisualizer();\n\n constructor() {\n super();\n this.#root = this.attachShadow({ mode: 'open' });\n this.player = new AVPlayerController();\n for (const type of eventTypes) {\n this.player.addEventListener(type, ((event: CustomEvent) => {\n if (type === 'av-ready') {\n if (this.player.source?.isHls) void ensureHlsElement();\n this.#resolvedSourceUrl = undefined;\n this.#resumeTime = this.player.getSavedPosition();\n this.#activePanel = this.player.config.activePanel;\n this.#render();\n void this.#resolveSource();\n void this.#loadActiveTranscript();\n } else if (type === 'av-canvaschange' || type === 'av-sourcechange') {\n if (this.player.source?.isHls) void ensureHlsElement();\n this.#resolvedSourceUrl = undefined;\n this.#transcriptCues = [];\n this.#transcriptIndex = 0;\n this.#render();\n void this.#resolveSource();\n void this.#loadActiveTranscript();\n } else if (type === 'av-configchange') {\n this.#activePanel = this.player.config.activePanel;\n void ensureMediaChrome(this.player.config.preferredLanguages[0]).then(() => this.#render());\n } else if (type === 'av-error') {\n this.#render();\n } else if (type === 'av-annotationschange') {\n if (this.#activePanel === 'annotations') this.#renderPanelOnly();\n } else if (type === 'av-timeupdate') {\n this.#syncTimedContent();\n } else if (type === 'av-seek') {\n this.#syncTimedContent((event.detail as AVPlayerEventMap['av-seek']).to, true);\n }\n this.dispatchEvent(new CustomEvent(type, {\n detail: event.detail,\n bubbles: true,\n composed: true,\n }));\n }) as EventListener);\n }\n }\n\n get manifest(): JsonObject | string | undefined {\n return this.#inputManifest;\n }\n\n get controller(): AVPlayerController {\n return this.player;\n }\n\n set manifest(value: JsonObject | string | undefined) {\n this.#inputManifest = value;\n if (this.isConnected && value !== undefined) void this.load(value);\n }\n\n get config(): AVPlayerConfig {\n return this.#config;\n }\n\n set config(value: AVPlayerConfig) {\n this.#config = value;\n this.player.configure(value);\n this.#activePanel = value.activePanel ?? this.player.config.activePanel;\n if (this.isConnected) this.#render();\n }\n\n connectedCallback(): void {\n this.#readConfigAttribute();\n void ensureMediaChrome(this.player.config.preferredLanguages[0]);\n this.#render();\n const source = this.#inputManifest ?? this.getAttribute('manifest-url') ?? undefined;\n if (source !== undefined) void this.load(source);\n }\n\n disconnectedCallback(): void {\n this.#visualizer.disconnect();\n this.player.destroy();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (!this.isConnected || oldValue === newValue) return;\n if (name === 'manifest-url' && newValue) {\n this.#inputManifest = newValue;\n void this.load(newValue);\n }\n if (name === 'config') {\n this.#readConfigAttribute();\n this.#render();\n }\n }\n\n async load(input: JsonObject | string): Promise<AVManifest> {\n this.#inputManifest = input;\n return await this.player.load(input);\n }\n\n play(): Promise<void> {\n return this.player.play();\n }\n\n pause(): void {\n this.player.pause();\n }\n\n seekTo(time: number): void {\n this.player.seekTo(time);\n }\n\n selectCanvas(indexOrId: number | string, options?: { time?: number; autoplay?: boolean }): AVCanvas | undefined {\n return this.player.selectCanvas(indexOrId, options);\n }\n\n #readConfigAttribute(): void {\n const attribute = this.getAttribute('config');\n if (!attribute) return;\n try {\n this.#config = JSON.parse(attribute) as AVPlayerConfig;\n this.player.configure(this.#config);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n\n #render(): void {\n this.#visualizer.disconnect();\n const state = this.player.state;\n const manifest = state.manifest;\n const canvas = this.player.canvas;\n const source = this.player.source;\n const ui = resolveStrings(this.player.config.strings);\n this.#root.innerHTML = `<style>${styles}</style><div class=\"shell\">\n <slot name=\"header\">\n ${manifest ? `<header class=\"header\"><h2>${escapeHtml(manifest.label)}</h2>${manifest.summary ? `<p>${escapeHtml(manifest.summary)}</p>` : ''}</header>` : ''}\n </slot>\n ${state.status === 'error' ? `<div class=\"error\" role=\"alert\">${escapeHtml(state.error?.message ?? ui.unableToLoadPlayer)}</div>` : ''}\n ${state.status === 'loading' ? `<p class=\"header\" role=\"status\">${escapeHtml(ui.loadingManifest)}</p>` : ''}\n ${manifest && canvas ? this.#renderReady(manifest, canvas, source?.kind ?? 'video') : ''}\n </div>`;\n this.#bindInteractions();\n const media = this.#root.querySelector('video, audio, hls-video') as HTMLMediaElement | null;\n if (media) {\n this.player.attachMedia(media);\n const art = this.#root.querySelector<HTMLElement>('.audio-art.visualizer');\n const visualizerMode = resolveAudioVisualizerMode(this.player.config.audioArt.visualizer);\n if (art && media instanceof HTMLAudioElement && visualizerMode) this.#visualizer.connect(media, art, visualizerMode);\n }\n this.#syncTimedContent();\n }\n\n #renderReady(manifest: AVManifest, canvas: AVCanvas, kind: 'audio' | 'video'): string {\n const source = this.player.source;\n const panels = this.player.config.panels;\n const controls = this.player.config.controls;\n const ui = resolveStrings(this.player.config.strings);\n const panelTabs = [\n panels.chapters ? ['chapters', ui.chapters] : undefined,\n panels.transcript ? ['transcript', ui.transcript] : undefined,\n panels.annotations ? ['annotations', ui.annotations] : undefined,\n panels.metadata ? ['metadata', ui.metadata] : undefined,\n panels.supplementalFiles ? ['files', ui.files] : undefined,\n ].filter((value): value is [string, string] => Boolean(value));\n const showPanel = this.#activePanel !== 'none' && panelTabs.length > 0;\n const showSourceSelector = controls.sourceSelector && canvas.sources.length > 1;\n const showDownload = controls.download && canvas.rendering.length > 0;\n const showPlayerToolbar = controls.navigation || controls.autoAdvance || showSourceSelector || showDownload;\n const visualizerMode = resolveAudioVisualizerMode(this.player.config.audioArt.visualizer);\n return `\n ${this.#resumeTime !== undefined ? `<div class=\"resume\">${escapeHtml(formatString(ui.resumePrompt, { time: formatTime(this.#resumeTime) }))} <button type=\"button\" data-action=\"resume\">${escapeHtml(ui.resume)}</button><button type=\"button\" data-action=\"dismiss-resume\">${escapeHtml(ui.startOver)}</button></div>` : ''}\n <div class=\"layout\" ${showPanel ? '' : 'style=\"grid-template-columns: 1fr\"'}>\n <section class=\"player-column\" aria-label=\"${escapeHtml(ui.mediaPlayer)}\">\n <slot name=\"before-player\"></slot>\n <media-controller ${kind === 'audio' ? 'audio' : ''} ${this.#mediaChromeLanguage()}>\n ${kind === 'audio' ? `<div class=\"audio-art ${visualizerMode ? `visualizer visualizer--${visualizerMode}` : ''}\">${audioArtContentHtml(canvas.label, this.#transcriptCues, Boolean(this.player.config.audioArt.transcript), visualizerMode)}</div>` : ''}\n ${source ? this.#mediaHtml(canvas, source.kind) : `<div class=\"audio-art\"><span>${escapeHtml(ui.noPlayableMedia)}</span></div>`}\n <slot name=\"player-overlay\"></slot>\n <slot name=\"controls\">\n <media-control-bar>\n <media-play-button></media-play-button>\n ${controls.seek ? `<media-seek-backward-button seekoffset=\"${controls.skipSeconds ?? 10}\"></media-seek-backward-button><media-seek-forward-button seekoffset=\"${controls.skipSeconds ?? 10}\"></media-seek-forward-button>` : ''}\n <media-time-display showduration></media-time-display>\n ${controls.seek ? '<media-time-range></media-time-range>' : ''}\n ${controls.volume ? '<media-mute-button></media-mute-button><media-volume-range></media-volume-range>' : ''}\n ${controls.captions && canvas.tracks.length > 0 ? '<media-captions-menu-button></media-captions-menu-button>' : ''}\n ${controls.playbackRate ? '<media-playback-rate-menu-button></media-playback-rate-menu-button>' : ''}\n ${controls.pictureInPicture && kind === 'video' ? '<media-pip-button></media-pip-button>' : ''}\n ${controls.fullscreen && kind === 'video' ? '<media-fullscreen-button></media-fullscreen-button>' : ''}\n </media-control-bar>\n ${controls.captions && canvas.tracks.length > 0 ? '<media-captions-menu hidden></media-captions-menu>' : ''}\n ${controls.playbackRate ? `<media-playback-rate-menu rates=\"${this.player.config.playbackRates.join(' ')}\" hidden></media-playback-rate-menu>` : ''}\n </slot>\n </media-controller>\n ${this.#searchMarkersHtml()}\n ${showPlayerToolbar ? `<div class=\"player-toolbar\">\n ${controls.navigation ? `<div class=\"group\">\n <button type=\"button\" data-action=\"previous\" ${canvas.index === 0 ? 'disabled' : ''} aria-label=\"${escapeHtml(ui.previousSection)}\">← ${escapeHtml(ui.previous)}</button>\n <button type=\"button\" data-action=\"next\" ${canvas.index === manifest.canvases.length - 1 && !this.player.state.repeat ? 'disabled' : ''} aria-label=\"${escapeHtml(ui.nextSection)}\">${escapeHtml(ui.next)} →</button>\n </div>` : ''}\n ${showSourceSelector || showDownload || controls.autoAdvance ? `<div class=\"group\">\n ${showSourceSelector ? `<label><span class=\"sr-only\">${escapeHtml(ui.mediaSource)}</span><select data-action=\"source\">${canvas.sources.map((item, index) => `<option value=\"${index}\" ${index === this.player.state.sourceIndex ? 'selected' : ''}>${escapeHtml(item.label ?? item.format ?? formatString(ui.sourceNumber, { number: index + 1 }))}</option>`).join('')}</select></label>` : ''}\n ${showDownload ? `<label><span class=\"sr-only\">${escapeHtml(ui.downloadMediaFile)}</span><select data-action=\"download\"><option value=\"\">${escapeHtml(ui.download)}…</option>${canvas.rendering.map((file) => `<option value=\"${escapeHtml(file.id)}\" data-filename=\"${escapeHtml(file.filename ?? '')}\">${escapeHtml(file.label)}</option>`).join('')}</select></label>` : ''}\n ${controls.autoAdvance ? `<label><input type=\"checkbox\" data-action=\"auto-advance\" ${this.player.state.autoAdvance ? 'checked' : ''}> ${escapeHtml(ui.autoAdvance)}</label>` : ''}\n </div>` : ''}\n </div>` : ''}\n <slot name=\"after-player\"></slot>\n </section>\n ${showPanel ? `<aside class=\"panel\">\n <nav class=\"tabs\" role=\"tablist\" aria-label=\"${escapeHtml(ui.mediaInformation)}\">${panelTabs.map(([id, tabLabel]) => `<button class=\"tab\" type=\"button\" role=\"tab\" data-panel=\"${id}\" aria-selected=\"${this.#activePanel === id}\">${escapeHtml(tabLabel)}</button>`).join('')}</nav>\n <div class=\"panel-content\" role=\"tabpanel\">${this.#panelHtml(manifest, canvas)}</div>\n </aside>` : ''}\n </div>`;\n }\n\n #mediaHtml(canvas: AVCanvas, kind: 'audio' | 'video'): string {\n const source = this.player.source;\n if (!source) return '';\n const tag = source.isHls ? 'hls-video' : kind;\n const sourceUrl = this.#resolvedSourceUrl ?? (this.player.config.resolveRequest ? '' : source.src);\n const attributes = [\n 'slot=\"media\"',\n sourceUrl ? `src=\"${escapeHtml(sourceUrl)}\"` : '',\n `preload=\"${this.player.config.preload}\"`,\n this.player.config.crossorigin ? `crossorigin=\"${this.player.config.crossorigin}\"` : '',\n kind === 'video' && canvas.poster ? `poster=\"${escapeHtml(canvas.poster)}\"` : '',\n `aria-label=\"${escapeHtml(canvas.label)}\"`,\n `data-canvasindex=\"${canvas.index}\"`,\n ].filter(Boolean).join(' ');\n const tracks = canvas.tracks.map((track) => `<track src=\"${escapeHtml(track.src)}\" kind=\"${track.kind}\" label=\"${escapeHtml(track.label)}\" ${track.language ? `srclang=\"${escapeHtml(track.language)}\"` : ''} ${track.default ? 'default' : ''}>`).join('');\n return `<${tag} ${attributes}>${tracks}</${tag}>`;\n }\n\n #mediaChromeLanguage(): string {\n const language = this.player.config.preferredLanguages.find((value) => value !== 'none');\n return language ? `lang=\"${escapeHtml(language)}\"` : '';\n }\n\n #panelHtml(manifest: AVManifest, canvas: AVCanvas): string {\n const ui = resolveStrings(this.player.config.strings);\n switch (this.#activePanel) {\n case 'chapters':\n return chapterHtml(manifest.chapters, canvas.id, ui);\n case 'transcript':\n return this.#transcriptHtml(canvas);\n case 'annotations':\n return this.#annotationsHtml(canvas.annotations);\n case 'metadata':\n return `<h3>${escapeHtml(canvas.label)}</h3>${metadataHtml([...manifest.metadata, ...canvas.metadata], ui)}${manifest.requiredStatement ? metadataHtml([manifest.requiredStatement], ui) : ''}${manifest.rights ? `<p><strong>${escapeHtml(ui.rights)}:</strong> <a href=\"${escapeHtml(manifest.rights)}\" target=\"_blank\" rel=\"noreferrer\">${escapeHtml(manifest.rights)}</a></p>` : ''}`;\n case 'files': {\n const files = [...manifest.rendering, ...canvas.rendering];\n return files.length > 0 ? `<ul class=\"file-list\">${files.map((file) => `<li><a href=\"${escapeHtml(file.id)}\" download=\"${escapeHtml(file.filename ?? '')}\">${escapeHtml(file.label)}</a>${file.format ? `<div class=\"time\">${escapeHtml(file.format)}</div>` : ''}</li>`).join('')}</ul>` : `<p class=\"empty\">${escapeHtml(ui.noSupplementalFiles)}</p>`;\n }\n default:\n return '';\n }\n }\n\n #transcriptHtml(canvas: AVCanvas): string {\n const ui = resolveStrings(this.player.config.strings);\n if (canvas.transcripts.length === 0) return `<p class=\"empty\">${escapeHtml(ui.noTranscript)}</p>`;\n const resource = canvas.transcripts[this.#transcriptIndex];\n const query = this.#transcriptQuery.trim();\n const visible = query\n ? this.#transcriptCues.filter((cue) => cue.text.toLowerCase().includes(query.toLowerCase()))\n : this.#transcriptCues;\n return `<div class=\"panel-tools\">\n ${canvas.transcripts.length > 1 ? `<select data-action=\"transcript\" aria-label=\"${escapeHtml(ui.transcript)}\">${canvas.transcripts.map((item, index) => `<option value=\"${index}\" ${index === this.#transcriptIndex ? 'selected' : ''}>${escapeHtml(item.label)}</option>`).join('')}</select>` : ''}\n ${this.player.config.transcript.search ? `<input type=\"search\" data-action=\"transcript-search\" value=\"${escapeHtml(this.#transcriptQuery)}\" placeholder=\"${escapeHtml(ui.searchTranscript)}\" aria-label=\"${escapeHtml(ui.searchTranscript)}\">` : ''}\n ${this.player.config.transcript.download && resource?.src ? `<a href=\"${escapeHtml(resource.src)}\" download>${escapeHtml(ui.download)}</a>` : ''}\n </div>\n ${this.#transcriptCues.length === 0 ? `<p class=\"empty\">${escapeHtml(ui.loadingTranscript)}</p>` : `<ol class=\"cue-list\">${visible.map((cue) => `<li class=\"cue\" data-cue-id=\"${escapeHtml(cue.id)}\" ${cue.start !== undefined ? `data-start=\"${cue.start}\" data-end=\"${cue.end ?? cue.start}\"` : ''}><button type=\"button\" ${cue.start === undefined ? 'disabled' : ''}>${cue.start !== undefined ? `<span class=\"time\">${formatTime(cue.start)}</span>` : ''}${cue.speaker ? `<span class=\"speaker\">${escapeHtml(cue.speaker)}</span>` : ''}<span>${highlight(cue.text, query)}</span></button></li>`).join('')}</ol>`}`;\n }\n\n #annotationsHtml(annotations: AVAnnotation[]): string {\n const ui = resolveStrings(this.player.config.strings);\n if (annotations.length === 0) return `<p class=\"empty\">${escapeHtml(ui.noAnnotations)}</p>`;\n return `<ol class=\"annotation-list\">${annotations.map((annotation) => `<li class=\"annotation\" data-start=\"${annotation.time?.start ?? ''}\" data-end=\"${annotation.time?.end ?? annotation.time?.start ?? ''}\"><button type=\"button\" ${annotation.time ? '' : 'disabled'}>${annotation.time ? `<span class=\"time\">${formatTime(annotation.time.start)}</span>` : ''}<span>${escapeHtml(annotation.text)}</span>${annotation.tags.length > 0 ? `<span class=\"tags\">${annotation.tags.map((tag) => `<span class=\"tag\">${escapeHtml(tag)}</span>`).join('')}</span>` : ''}</button></li>`).join('')}</ol>`;\n }\n\n #searchMarkersHtml(): string {\n const ui = resolveStrings(this.player.config.strings);\n const query = this.#transcriptQuery.trim().toLowerCase();\n const duration = this.player.state.duration || this.player.canvas?.duration || 0;\n if (!query || !this.player.config.transcript.showSearchMarkers || duration <= 0) return '';\n const matches = this.#transcriptCues.filter((cue) => cue.start !== undefined && cue.text.toLowerCase().includes(query));\n if (matches.length === 0) return '';\n return `<div class=\"search-markers\" aria-label=\"${escapeHtml(ui.transcriptSearchMatches)}\">${matches.map((cue) => `<button type=\"button\" class=\"search-marker\" data-search-time=\"${cue.start}\" style=\"left:${Math.min(100, Math.max(0, ((cue.start ?? 0) / duration) * 100))}%\" aria-label=\"${escapeHtml(formatString(ui.searchMatchAt, { time: formatTime(cue.start ?? 0) }))}\"></button>`).join('')}</div>`;\n }\n\n #bindInteractions(): void {\n this.#root.querySelectorAll<HTMLElement>('[data-panel]').forEach((button) => button.addEventListener('click', () => {\n this.#activePanel = button.dataset.panel as NonNullable<AVPlayerConfig['activePanel']>;\n this.#renderPanelOnly();\n if (this.#activePanel === 'transcript') void this.#loadActiveTranscript();\n }));\n this.#root.querySelector<HTMLElement>('[data-action=previous]')?.addEventListener('click', () => this.player.previous({ autoplay: this.player.state.status === 'playing' }));\n this.#root.querySelector<HTMLElement>('[data-action=next]')?.addEventListener('click', () => this.player.next({ autoplay: this.player.state.status === 'playing' }));\n this.#root.querySelector<HTMLSelectElement>('[data-action=source]')?.addEventListener('change', (event) => this.player.selectSource(Number((event.target as HTMLSelectElement).value)));\n this.#root.querySelector<HTMLSelectElement>('[data-action=download]')?.addEventListener('change', (event) => {\n const select = event.target as HTMLSelectElement;\n if (!select.value) return;\n const anchor = document.createElement('a');\n anchor.href = select.value;\n anchor.download = select.selectedOptions[0]?.dataset.filename ?? '';\n anchor.click();\n select.value = '';\n });\n this.#root.querySelector<HTMLInputElement>('[data-action=auto-advance]')?.addEventListener('change', (event) => this.player.setAutoAdvance((event.target as HTMLInputElement).checked));\n this.#root.querySelector<HTMLElement>('[data-action=resume]')?.addEventListener('click', () => {\n if (this.#resumeTime !== undefined) this.player.seekTo(this.#resumeTime);\n this.#resumeTime = undefined;\n this.#render();\n });\n this.#root.querySelector<HTMLElement>('[data-action=dismiss-resume]')?.addEventListener('click', () => {\n this.#resumeTime = undefined;\n this.#render();\n });\n this.#bindPanelInteractions();\n }\n\n #bindPanelInteractions(): void {\n this.#root.querySelectorAll<HTMLElement>('[data-canvas]').forEach((button) => button.addEventListener('click', () => {\n const canvasId = button.dataset.canvas;\n if (canvasId) this.player.selectCanvas(canvasId, { time: Number(button.dataset.time ?? 0), autoplay: true });\n }));\n this.#root.querySelector<HTMLSelectElement>('[data-action=transcript]')?.addEventListener('change', (event) => {\n this.#transcriptIndex = Number((event.target as HTMLSelectElement).value);\n this.#transcriptCues = [];\n this.#renderPanelOnly();\n void this.#loadActiveTranscript();\n });\n this.#root.querySelector<HTMLInputElement>('[data-action=transcript-search]')?.addEventListener('input', (event) => {\n this.#transcriptQuery = (event.target as HTMLInputElement).value;\n const selection = (event.target as HTMLInputElement).selectionStart;\n this.#renderPanelOnly();\n const input = this.#root.querySelector<HTMLInputElement>('[data-action=transcript-search]');\n input?.focus();\n if (selection !== null) input?.setSelectionRange(selection, selection);\n });\n this.#root.querySelectorAll<HTMLElement>('.cue[data-start] button, .annotation[data-start] button').forEach((button) => button.addEventListener('click', () => {\n const row = button.parentElement;\n const start = Number(row?.dataset.start);\n if (Number.isFinite(start)) {\n this.player.seekTo(start);\n playFromInteraction(this.player, this);\n }\n }));\n this.#root.querySelectorAll<HTMLElement>('[data-search-time]').forEach((button) => button.addEventListener('click', () => {\n const time = Number(button.dataset.searchTime);\n if (Number.isFinite(time)) this.player.seekTo(time);\n }));\n }\n\n #renderPanelOnly(): void {\n const manifest = this.player.manifest;\n const canvas = this.player.canvas;\n if (!manifest || !canvas) return;\n this.#root.querySelectorAll<HTMLElement>('[data-panel]').forEach((tab) => {\n tab.setAttribute('aria-selected', String(tab.dataset.panel === this.#activePanel));\n });\n const content = this.#root.querySelector<HTMLElement>('.panel-content');\n if (content) content.innerHTML = this.#panelHtml(manifest, canvas);\n this.#root.querySelector('.search-markers')?.remove();\n const toolbar = this.#root.querySelector('.player-toolbar');\n const markers = this.#searchMarkersHtml();\n if (toolbar && markers) toolbar.insertAdjacentHTML('beforebegin', markers);\n this.#bindPanelInteractions();\n }\n\n async #loadActiveTranscript(): Promise<void> {\n const resource = this.player.canvas?.transcripts[this.#transcriptIndex];\n if (!resource) return;\n const token = ++this.#loadingToken;\n try {\n const transcriptOptions: Parameters<typeof loadTranscript>[1] = {};\n if (this.player.config.fetch) transcriptOptions.fetch = this.player.config.fetch;\n if (this.player.config.requestInit) transcriptOptions.requestInit = this.player.config.requestInit;\n if (this.player.config.transcript.showNotes !== undefined) transcriptOptions.showNotes = this.player.config.transcript.showNotes;\n if (this.player.config.transcript.showMetadata !== undefined) transcriptOptions.showMetadata = this.player.config.transcript.showMetadata;\n const cues = await loadTranscript(resource, transcriptOptions);\n if (token !== this.#loadingToken) return;\n this.#transcriptCues = cues;\n this.#renderAudioArt();\n if (this.#activePanel === 'transcript') this.#renderPanelOnly();\n } catch (cause) {\n if (token !== this.#loadingToken) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n this.#transcriptCues = [];\n if (this.#activePanel === 'transcript') this.#renderPanelOnly();\n }\n }\n\n async #resolveSource(): Promise<void> {\n if (!this.player.config.resolveRequest) return;\n const token = ++this.#sourceToken;\n try {\n const sourceUrl = await this.player.resolvedSourceUrl();\n if (token !== this.#sourceToken || !sourceUrl) return;\n this.#resolvedSourceUrl = sourceUrl;\n const media = this.#root.querySelector('video, audio, hls-video') as HTMLMediaElement | null;\n if (media) media.setAttribute('src', sourceUrl);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n\n #syncTimedContent(time = this.player.state.currentTime, instant = false): void {\n syncAudioArtTranscript(this.#root, time, instant);\n const rows = this.#root.querySelectorAll<HTMLElement>('[data-start][data-end]');\n let active: HTMLElement | undefined;\n rows.forEach((row) => {\n const start = Number(row.dataset.start);\n const end = Number(row.dataset.end);\n const isActive = Number.isFinite(start) && time >= start && (!Number.isFinite(end) || time < end);\n row.querySelector('button')?.classList.toggle('active', isActive);\n if (isActive) active = row;\n });\n if (active && this.player.config.transcript.autoScroll) {\n active.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }\n }\n\n #renderAudioArt(): void {\n const art = this.#root.querySelector<HTMLElement>('.audio-art');\n const canvas = this.player.canvas;\n if (!art || !canvas || this.player.source?.kind !== 'audio') return;\n const text = art.querySelector<HTMLElement>('.audio-art-text');\n if (text) text.innerHTML = audioArtTranscriptHtml(canvas.label, this.#transcriptCues, Boolean(this.player.config.audioArt.transcript));\n syncAudioArtTranscript(art, this.player.state.currentTime);\n }\n}\n\nexport const defineMangoAVMedia = (tagName = 'mango-av-media'): typeof MangoAVMediaElement => {\n if (typeof customElements === 'undefined') return MangoAVMediaElement;\n if (!customElements.get(tagName)) customElements.define(tagName, MangoAVMediaElement);\n return MangoAVMediaElement;\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
AudioArtVisualizer,
|
|
3
|
+
audioArtContentHtml,
|
|
4
|
+
audioArtTranscriptHtml,
|
|
5
|
+
ensureMediaChrome,
|
|
6
|
+
resolveAudioVisualizerMode,
|
|
7
|
+
syncAudioArtTranscript
|
|
8
|
+
} from "./chunk-6JIJRMNE.js";
|
|
4
9
|
import {
|
|
5
10
|
AVControllerElement,
|
|
6
11
|
componentTheme
|
|
7
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HM72GHCH.js";
|
|
13
|
+
import {
|
|
14
|
+
loadTranscript
|
|
15
|
+
} from "./chunk-AZFOTEAO.js";
|
|
8
16
|
import {
|
|
9
17
|
escapeHtml,
|
|
10
18
|
formatString,
|
|
11
19
|
resolveStrings
|
|
12
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-EV6YN7WV.js";
|
|
13
21
|
|
|
14
22
|
// src/components/mango-av-player.ts
|
|
15
23
|
var hlsElementRegistration;
|
|
@@ -25,8 +33,17 @@ var styles = `${componentTheme}
|
|
|
25
33
|
video, hls-video { display: block; height: 100%; object-fit: contain; width: 100%; }
|
|
26
34
|
audio { width: 100%; }
|
|
27
35
|
media-control-bar { width: 100%; }
|
|
28
|
-
.audio-art { align-items: center; aspect-ratio: 16 / 7; background: linear-gradient(
|
|
29
|
-
.audio-art
|
|
36
|
+
.audio-art { --mango-av-wave-edge-strength: 0%; --mango-av-wave-mid-strength: 0%; --mango-av-wave-rise: 8%; --mango-av-wave-strength: 0%; align-items: center; aspect-ratio: 16 / 7; background: linear-gradient(#09080d, #111019); display: flex; justify-content: center; overflow: hidden; padding: 2rem; position: relative; text-align: center; }
|
|
37
|
+
.audio-art.visualizer--pulse { background: radial-gradient(ellipse 140% 72% at 50% calc(100% + var(--mango-av-wave-rise)), color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-strength), transparent) 0%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-mid-strength), transparent) 40%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-edge-strength), transparent) 62%, transparent 78%), linear-gradient(#09080d, #111019); }
|
|
38
|
+
.audio-art-text { display: contents; }
|
|
39
|
+
.audio-art-visualizer-canvas { height: 100%; inset: 0; pointer-events: none; position: absolute; width: 100%; }
|
|
40
|
+
.audio-art-title { font-size: clamp(1.1rem, 3vw, 2rem); font-weight: 700; position: relative; z-index: 1; }
|
|
41
|
+
.audio-art-transcript { height: 100%; inset: 0; overflow: hidden; position: absolute; z-index: 1; }
|
|
42
|
+
.audio-art-cue { align-items: center; display: flex; flex-direction: column; font-size: clamp(.7rem, 1.3vw, .875rem); font-weight: 550; gap: .15rem; left: 12%; line-height: 1.35; position: absolute; right: 12%; top: 50%; transition: opacity 360ms ease, transform 480ms cubic-bezier(.22, 1, .36, 1); }
|
|
43
|
+
.audio-art-transcript.seeking .audio-art-cue { transition: none; }
|
|
44
|
+
.audio-art-cue.active { font-size: clamp(.78rem, 1.5vw, 1rem); font-weight: 650; }
|
|
45
|
+
.audio-art-cue > span:last-child { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
|
|
46
|
+
.audio-art-speaker { font-size: .7em; letter-spacing: .04em; text-transform: uppercase; }
|
|
30
47
|
.toolbar { align-items: center; background: #151518; display: flex; flex-wrap: wrap; gap: .5rem; justify-content: space-between; padding: .55rem .7rem; }
|
|
31
48
|
.toolbar button, .toolbar select { background: #29292e; border: 1px solid #44444a; border-radius: .35rem; color: white; padding: .4rem .55rem; }
|
|
32
49
|
.group { align-items: center; display: flex; gap: .45rem; }
|
|
@@ -40,6 +57,9 @@ var MangoAVPlayerElement = class extends AVControllerElement {
|
|
|
40
57
|
#config = {};
|
|
41
58
|
#resolvedSourceUrl;
|
|
42
59
|
#sourceToken = 0;
|
|
60
|
+
#transcriptCues = [];
|
|
61
|
+
#transcriptToken = 0;
|
|
62
|
+
#visualizer = new AudioArtVisualizer();
|
|
43
63
|
constructor() {
|
|
44
64
|
super();
|
|
45
65
|
this.#root = this.attachShadow({ mode: "open" });
|
|
@@ -66,6 +86,10 @@ var MangoAVPlayerElement = class extends AVControllerElement {
|
|
|
66
86
|
const source = this.#manifestInput ?? this.getAttribute("manifest-url") ?? void 0;
|
|
67
87
|
if (source !== void 0 && !this.controller.manifest) void this.load(source);
|
|
68
88
|
}
|
|
89
|
+
disconnectedCallback() {
|
|
90
|
+
this.#visualizer.disconnect();
|
|
91
|
+
super.disconnectedCallback();
|
|
92
|
+
}
|
|
69
93
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
70
94
|
if (!this.isConnected || oldValue === newValue) return;
|
|
71
95
|
if (name === "manifest-url" && newValue) {
|
|
@@ -93,20 +117,34 @@ var MangoAVPlayerElement = class extends AVControllerElement {
|
|
|
93
117
|
return this.controller.selectCanvas(indexOrId, options);
|
|
94
118
|
}
|
|
95
119
|
controllerChanged() {
|
|
120
|
+
this.#transcriptCues = [];
|
|
96
121
|
this.#render();
|
|
122
|
+
void this.#loadTranscript();
|
|
97
123
|
}
|
|
98
124
|
handleControllerEvent(type, event) {
|
|
99
125
|
if (type === "av-configchange") {
|
|
100
126
|
this.#resolvedSourceUrl = void 0;
|
|
101
127
|
void ensureMediaChrome(this.controller.config.preferredLanguages[0]).then(() => {
|
|
102
128
|
this.#render();
|
|
129
|
+
void this.#loadTranscript();
|
|
103
130
|
void this.#resolveSource();
|
|
104
131
|
});
|
|
105
|
-
} else if (type === "av-ready" || type === "av-canvaschange"
|
|
132
|
+
} else if (type === "av-ready" || type === "av-canvaschange") {
|
|
106
133
|
this.#resolvedSourceUrl = void 0;
|
|
134
|
+
this.#transcriptCues = [];
|
|
107
135
|
if (this.controller.source?.isHls) void ensureHlsElement();
|
|
108
136
|
this.#render();
|
|
137
|
+
void this.#loadTranscript();
|
|
109
138
|
void this.#resolveSource();
|
|
139
|
+
} else if (type === "av-sourcechange" || type === "av-error") {
|
|
140
|
+
this.#resolvedSourceUrl = void 0;
|
|
141
|
+
if (this.controller.source?.isHls) void ensureHlsElement();
|
|
142
|
+
this.#render();
|
|
143
|
+
void this.#resolveSource();
|
|
144
|
+
} else if (type === "av-seek") {
|
|
145
|
+
syncAudioArtTranscript(this.#root, event.detail.to, true);
|
|
146
|
+
} else if (type === "av-timeupdate" || type === "av-statechange") {
|
|
147
|
+
syncAudioArtTranscript(this.#root, this.controller.state.currentTime);
|
|
110
148
|
}
|
|
111
149
|
this.dispatchEvent(new CustomEvent(type, { detail: event.detail, bubbles: true, composed: true }));
|
|
112
150
|
}
|
|
@@ -122,6 +160,7 @@ var MangoAVPlayerElement = class extends AVControllerElement {
|
|
|
122
160
|
}
|
|
123
161
|
}
|
|
124
162
|
#render() {
|
|
163
|
+
this.#visualizer.disconnect();
|
|
125
164
|
const state = this.controller.state;
|
|
126
165
|
const canvas = this.controller.canvas;
|
|
127
166
|
const source = this.controller.source;
|
|
@@ -133,7 +172,13 @@ var MangoAVPlayerElement = class extends AVControllerElement {
|
|
|
133
172
|
${canvas && source ? this.#readyHtml(canvas, source) : state.status !== "loading" && state.status !== "error" ? `<div class="audio-art"><span>${escapeHtml(ui.noMediaLoaded)}</span></div>` : ""}
|
|
134
173
|
</div>`;
|
|
135
174
|
const media = this.#root.querySelector("video, audio, hls-video");
|
|
136
|
-
if (media)
|
|
175
|
+
if (media) {
|
|
176
|
+
this.controller.attachMedia(media);
|
|
177
|
+
const art = this.#root.querySelector(".audio-art.visualizer");
|
|
178
|
+
const visualizerMode = resolveAudioVisualizerMode(this.controller.config.audioArt.visualizer);
|
|
179
|
+
if (art && media instanceof HTMLAudioElement && visualizerMode) this.#visualizer.connect(media, art, visualizerMode);
|
|
180
|
+
}
|
|
181
|
+
syncAudioArtTranscript(this.#root, this.controller.state.currentTime);
|
|
137
182
|
this.#bind();
|
|
138
183
|
}
|
|
139
184
|
#readyHtml(canvas, source) {
|
|
@@ -142,8 +187,11 @@ var MangoAVPlayerElement = class extends AVControllerElement {
|
|
|
142
187
|
const kind = source.kind;
|
|
143
188
|
const ui = resolveStrings(this.controller.config.strings);
|
|
144
189
|
const language = this.controller.config.preferredLanguages.find((value) => value !== "none");
|
|
190
|
+
const showSourceSelector = controls.sourceSelector && canvas.sources.length > 1;
|
|
191
|
+
const showToolbar = controls.navigation || controls.autoAdvance || showSourceSelector;
|
|
192
|
+
const visualizerMode = resolveAudioVisualizerMode(this.controller.config.audioArt.visualizer);
|
|
145
193
|
return `<media-controller ${kind === "audio" ? "audio" : ""} ${language ? `lang="${escapeHtml(language)}"` : ""}>
|
|
146
|
-
${kind === "audio" ? `<div class="audio-art"
|
|
194
|
+
${kind === "audio" ? `<div class="audio-art ${visualizerMode ? `visualizer visualizer--${visualizerMode}` : ""}">${audioArtContentHtml(canvas.label, this.#transcriptCues, Boolean(this.controller.config.audioArt.transcript), visualizerMode)}</div>` : ""}
|
|
147
195
|
${this.#mediaHtml(canvas, source)}
|
|
148
196
|
<slot name="overlay"></slot>
|
|
149
197
|
<slot name="controls">
|
|
@@ -162,16 +210,16 @@ var MangoAVPlayerElement = class extends AVControllerElement {
|
|
|
162
210
|
${controls.playbackRate ? `<media-playback-rate-menu rates="${this.controller.config.playbackRates.join(" ")}" hidden></media-playback-rate-menu>` : ""}
|
|
163
211
|
</slot>
|
|
164
212
|
</media-controller>
|
|
165
|
-
|
|
166
|
-
|
|
213
|
+
${showToolbar ? `<div class="toolbar">
|
|
214
|
+
${controls.navigation ? `<div class="group">
|
|
167
215
|
<button type="button" data-action="previous" ${canvas.index === 0 ? "disabled" : ""} aria-label="${escapeHtml(ui.previousSection)}">\u2190 ${escapeHtml(ui.previous)}</button>
|
|
168
216
|
<button type="button" data-action="next" ${canvas.index === (manifest?.canvases.length ?? 1) - 1 && !this.controller.state.repeat ? "disabled" : ""} aria-label="${escapeHtml(ui.nextSection)}">${escapeHtml(ui.next)} \u2192</button>
|
|
169
|
-
</div
|
|
170
|
-
|
|
171
|
-
${
|
|
172
|
-
|
|
173
|
-
</div
|
|
174
|
-
</div
|
|
217
|
+
</div>` : ""}
|
|
218
|
+
${showSourceSelector || controls.autoAdvance ? `<div class="group">
|
|
219
|
+
${showSourceSelector ? `<label><span class="sr-only">${escapeHtml(ui.mediaSource)}</span><select data-action="source">${canvas.sources.map((item, index) => `<option value="${index}" ${index === this.controller.state.sourceIndex ? "selected" : ""}>${escapeHtml(item.label ?? item.format ?? formatString(ui.sourceNumber, { number: index + 1 }))}</option>`).join("")}</select></label>` : ""}
|
|
220
|
+
${controls.autoAdvance ? `<label><input type="checkbox" data-action="auto-advance" ${this.controller.state.autoAdvance ? "checked" : ""}> ${escapeHtml(ui.autoAdvance)}</label>` : ""}
|
|
221
|
+
</div>` : ""}
|
|
222
|
+
</div>` : ""}`;
|
|
175
223
|
}
|
|
176
224
|
#mediaHtml(canvas, source) {
|
|
177
225
|
const tag = source.isHls ? "hls-video" : source.kind;
|
|
@@ -207,6 +255,32 @@ var MangoAVPlayerElement = class extends AVControllerElement {
|
|
|
207
255
|
this.dispatchEvent(new CustomEvent("av-error", { detail: { error }, bubbles: true, composed: true }));
|
|
208
256
|
}
|
|
209
257
|
}
|
|
258
|
+
async #loadTranscript() {
|
|
259
|
+
const resource = this.controller.canvas?.transcripts[0];
|
|
260
|
+
if (!resource || !this.controller.config.audioArt.transcript) return;
|
|
261
|
+
const token = ++this.#transcriptToken;
|
|
262
|
+
const options = {};
|
|
263
|
+
if (this.controller.config.fetch) options.fetch = this.controller.config.fetch;
|
|
264
|
+
if (this.controller.config.requestInit) options.requestInit = this.controller.config.requestInit;
|
|
265
|
+
if (this.controller.config.transcript.showNotes !== void 0) options.showNotes = this.controller.config.transcript.showNotes;
|
|
266
|
+
if (this.controller.config.transcript.showMetadata !== void 0) options.showMetadata = this.controller.config.transcript.showMetadata;
|
|
267
|
+
try {
|
|
268
|
+
const cues = await loadTranscript(resource, options);
|
|
269
|
+
if (token !== this.#transcriptToken) return;
|
|
270
|
+
this.#transcriptCues = cues;
|
|
271
|
+
const art = this.#root.querySelector(".audio-art");
|
|
272
|
+
const canvas = this.controller.canvas;
|
|
273
|
+
if (art && canvas && this.controller.source?.kind === "audio") {
|
|
274
|
+
const text = art.querySelector(".audio-art-text");
|
|
275
|
+
if (text) text.innerHTML = audioArtTranscriptHtml(canvas.label, cues, true);
|
|
276
|
+
syncAudioArtTranscript(art, this.controller.state.currentTime);
|
|
277
|
+
}
|
|
278
|
+
} catch (cause) {
|
|
279
|
+
if (token !== this.#transcriptToken) return;
|
|
280
|
+
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
281
|
+
this.dispatchEvent(new CustomEvent("av-error", { detail: { error }, bubbles: true, composed: true }));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
210
284
|
};
|
|
211
285
|
var defineMangoAVPlayer = (tagName = "mango-av-player") => {
|
|
212
286
|
if (typeof customElements === "undefined") return MangoAVPlayerElement;
|
|
@@ -218,4 +292,4 @@ export {
|
|
|
218
292
|
MangoAVPlayerElement,
|
|
219
293
|
defineMangoAVPlayer
|
|
220
294
|
};
|
|
221
|
-
//# sourceMappingURL=chunk-
|
|
295
|
+
//# sourceMappingURL=chunk-D7W5UINF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/mango-av-player.ts"],"sourcesContent":["import { AVControllerElement } from './controller-element';\nimport { componentTheme } from './component-styles';\nimport { ensureMediaChrome } from './media-chrome';\nimport { AudioArtVisualizer, audioArtContentHtml, audioArtTranscriptHtml, resolveAudioVisualizerMode, syncAudioArtTranscript } from './audio-art';\nimport { loadTranscript } from '../transcript';\nimport type { AVCanvas, AVManifest, AVPlayerConfig, AVPlayerEventMap, JsonObject, MediaSource, TranscriptCue } from '../types';\nimport { escapeHtml, formatString, resolveStrings } from '../utils';\n\nlet hlsElementRegistration: Promise<unknown> | undefined;\nconst ensureHlsElement = (): Promise<unknown> => {\n hlsElementRegistration ??= import('hls-video-element');\n return hlsElementRegistration;\n};\n\nconst styles = `${componentTheme}\n :host { --mango-av-player-aspect-ratio: 16 / 9; }\n .player { background: #08080a; border-radius: var(--mango-av-radius); color: white; overflow: clip; position: relative; }\n media-controller { display: block; width: 100%; }\n media-controller:not([audio]) { aspect-ratio: var(--mango-av-player-aspect-ratio); }\n video, hls-video { display: block; height: 100%; object-fit: contain; width: 100%; }\n audio { width: 100%; }\n media-control-bar { width: 100%; }\n .audio-art { --mango-av-wave-edge-strength: 0%; --mango-av-wave-mid-strength: 0%; --mango-av-wave-rise: 8%; --mango-av-wave-strength: 0%; align-items: center; aspect-ratio: 16 / 7; background: linear-gradient(#09080d, #111019); display: flex; justify-content: center; overflow: hidden; padding: 2rem; position: relative; text-align: center; }\n .audio-art.visualizer--pulse { background: radial-gradient(ellipse 140% 72% at 50% calc(100% + var(--mango-av-wave-rise)), color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-strength), transparent) 0%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-mid-strength), transparent) 40%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-edge-strength), transparent) 62%, transparent 78%), linear-gradient(#09080d, #111019); }\n .audio-art-text { display: contents; }\n .audio-art-visualizer-canvas { height: 100%; inset: 0; pointer-events: none; position: absolute; width: 100%; }\n .audio-art-title { font-size: clamp(1.1rem, 3vw, 2rem); font-weight: 700; position: relative; z-index: 1; }\n .audio-art-transcript { height: 100%; inset: 0; overflow: hidden; position: absolute; z-index: 1; }\n .audio-art-cue { align-items: center; display: flex; flex-direction: column; font-size: clamp(.7rem, 1.3vw, .875rem); font-weight: 550; gap: .15rem; left: 12%; line-height: 1.35; position: absolute; right: 12%; top: 50%; transition: opacity 360ms ease, transform 480ms cubic-bezier(.22, 1, .36, 1); }\n .audio-art-transcript.seeking .audio-art-cue { transition: none; }\n .audio-art-cue.active { font-size: clamp(.78rem, 1.5vw, 1rem); font-weight: 650; }\n .audio-art-cue > span:last-child { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }\n .audio-art-speaker { font-size: .7em; letter-spacing: .04em; text-transform: uppercase; }\n .toolbar { align-items: center; background: #151518; display: flex; flex-wrap: wrap; gap: .5rem; justify-content: space-between; padding: .55rem .7rem; }\n .toolbar button, .toolbar select { background: #29292e; border: 1px solid #44444a; border-radius: .35rem; color: white; padding: .4rem .55rem; }\n .group { align-items: center; display: flex; gap: .45rem; }\n .error { background: #fff0f0; color: #8a1717; padding: 1rem; }\n .sr-only { clip: rect(0,0,0,0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; }\n`;\n\nexport class MangoAVPlayerElement extends AVControllerElement {\n static observedAttributes = ['manifest-url', 'config'];\n\n #root: ShadowRoot;\n #manifestInput: JsonObject | string | undefined;\n #config: AVPlayerConfig = {};\n #resolvedSourceUrl: string | undefined;\n #sourceToken = 0;\n #transcriptCues: TranscriptCue[] = [];\n #transcriptToken = 0;\n #visualizer = new AudioArtVisualizer();\n\n constructor() {\n super();\n this.#root = this.attachShadow({ mode: 'open' });\n }\n\n get manifest(): JsonObject | string | undefined {\n return this.#manifestInput;\n }\n\n set manifest(value: JsonObject | string | undefined) {\n this.#manifestInput = value;\n if (this.isConnected && value !== undefined) void this.load(value);\n }\n\n get config(): AVPlayerConfig {\n return this.#config;\n }\n\n set config(value: AVPlayerConfig) {\n this.#config = value;\n this.controller.configure(value);\n this.#render();\n }\n\n override connectedCallback(): void {\n this.#readConfigAttribute();\n void ensureMediaChrome(this.controller.config.preferredLanguages[0]);\n super.connectedCallback();\n const source = this.#manifestInput ?? this.getAttribute('manifest-url') ?? undefined;\n if (source !== undefined && !this.controller.manifest) void this.load(source);\n }\n\n override disconnectedCallback(): void {\n this.#visualizer.disconnect();\n super.disconnectedCallback();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (!this.isConnected || oldValue === newValue) return;\n if (name === 'manifest-url' && newValue) {\n this.#manifestInput = newValue;\n void this.load(newValue);\n } else if (name === 'config') {\n this.#readConfigAttribute();\n this.#render();\n }\n }\n\n async load(input: JsonObject | string): Promise<AVManifest> {\n this.#manifestInput = input;\n return await this.controller.load(input);\n }\n\n play(): Promise<void> { return this.controller.play(); }\n pause(): void { this.controller.pause(); }\n seekTo(time: number): void { this.controller.seekTo(time); }\n selectCanvas(indexOrId: number | string, options?: { time?: number; autoplay?: boolean }): AVCanvas | undefined {\n return this.controller.selectCanvas(indexOrId, options);\n }\n\n protected controllerChanged(): void {\n this.#transcriptCues = [];\n this.#render();\n void this.#loadTranscript();\n }\n\n protected handleControllerEvent<K extends keyof AVPlayerEventMap>(type: K, event: CustomEvent<AVPlayerEventMap[K]>): void {\n if (type === 'av-configchange') {\n this.#resolvedSourceUrl = undefined;\n void ensureMediaChrome(this.controller.config.preferredLanguages[0]).then(() => {\n this.#render();\n void this.#loadTranscript();\n void this.#resolveSource();\n });\n } else if (type === 'av-ready' || type === 'av-canvaschange') {\n this.#resolvedSourceUrl = undefined;\n this.#transcriptCues = [];\n if (this.controller.source?.isHls) void ensureHlsElement();\n this.#render();\n void this.#loadTranscript();\n void this.#resolveSource();\n } else if (type === 'av-sourcechange' || type === 'av-error') {\n this.#resolvedSourceUrl = undefined;\n if (this.controller.source?.isHls) void ensureHlsElement();\n this.#render();\n void this.#resolveSource();\n } else if (type === 'av-seek') {\n syncAudioArtTranscript(this.#root, (event.detail as AVPlayerEventMap['av-seek']).to, true);\n } else if (type === 'av-timeupdate' || type === 'av-statechange') {\n syncAudioArtTranscript(this.#root, this.controller.state.currentTime);\n }\n this.dispatchEvent(new CustomEvent(type, { detail: event.detail, bubbles: true, composed: true }));\n }\n\n #readConfigAttribute(): void {\n const value = this.getAttribute('config');\n if (!value) return;\n try {\n this.#config = JSON.parse(value) as AVPlayerConfig;\n this.controller.configure(this.#config);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n\n #render(): void {\n this.#visualizer.disconnect();\n const state = this.controller.state;\n const canvas = this.controller.canvas;\n const source = this.controller.source;\n const ui = resolveStrings(this.controller.config.strings);\n this.#root.innerHTML = `<style>${styles}</style>\n <div class=\"player\">\n ${state.status === 'loading' ? `<p role=\"status\">${escapeHtml(ui.loadingManifest)}</p>` : ''}\n ${state.status === 'error' ? `<div class=\"error\" role=\"alert\">${escapeHtml(state.error?.message ?? ui.unableToLoadMedia)}</div>` : ''}\n ${canvas && source ? this.#readyHtml(canvas, source) : state.status !== 'loading' && state.status !== 'error' ? `<div class=\"audio-art\"><span>${escapeHtml(ui.noMediaLoaded)}</span></div>` : ''}\n </div>`;\n const media = this.#root.querySelector('video, audio, hls-video') as HTMLMediaElement | null;\n if (media) {\n this.controller.attachMedia(media);\n const art = this.#root.querySelector<HTMLElement>('.audio-art.visualizer');\n const visualizerMode = resolveAudioVisualizerMode(this.controller.config.audioArt.visualizer);\n if (art && media instanceof HTMLAudioElement && visualizerMode) this.#visualizer.connect(media, art, visualizerMode);\n }\n syncAudioArtTranscript(this.#root, this.controller.state.currentTime);\n this.#bind();\n }\n\n #readyHtml(canvas: AVCanvas, source: MediaSource): string {\n const controls = this.controller.config.controls;\n const manifest = this.controller.manifest;\n const kind = source.kind;\n const ui = resolveStrings(this.controller.config.strings);\n const language = this.controller.config.preferredLanguages.find((value) => value !== 'none');\n const showSourceSelector = controls.sourceSelector && canvas.sources.length > 1;\n const showToolbar = controls.navigation || controls.autoAdvance || showSourceSelector;\n const visualizerMode = resolveAudioVisualizerMode(this.controller.config.audioArt.visualizer);\n return `<media-controller ${kind === 'audio' ? 'audio' : ''} ${language ? `lang=\"${escapeHtml(language)}\"` : ''}>\n ${kind === 'audio' ? `<div class=\"audio-art ${visualizerMode ? `visualizer visualizer--${visualizerMode}` : ''}\">${audioArtContentHtml(canvas.label, this.#transcriptCues, Boolean(this.controller.config.audioArt.transcript), visualizerMode)}</div>` : ''}\n ${this.#mediaHtml(canvas, source)}\n <slot name=\"overlay\"></slot>\n <slot name=\"controls\">\n <media-control-bar>\n <media-play-button></media-play-button>\n ${controls.seek ? `<media-seek-backward-button seekoffset=\"${controls.skipSeconds ?? 10}\"></media-seek-backward-button><media-seek-forward-button seekoffset=\"${controls.skipSeconds ?? 10}\"></media-seek-forward-button>` : ''}\n <media-time-display showduration></media-time-display>\n ${controls.seek ? '<media-time-range></media-time-range>' : ''}\n ${controls.volume ? '<media-mute-button></media-mute-button><media-volume-range></media-volume-range>' : ''}\n ${controls.captions && canvas.tracks.length > 0 ? '<media-captions-menu-button></media-captions-menu-button>' : ''}\n ${controls.playbackRate ? '<media-playback-rate-menu-button></media-playback-rate-menu-button>' : ''}\n ${controls.pictureInPicture && kind === 'video' ? '<media-pip-button></media-pip-button>' : ''}\n ${controls.fullscreen && kind === 'video' ? '<media-fullscreen-button></media-fullscreen-button>' : ''}\n </media-control-bar>\n ${controls.captions && canvas.tracks.length > 0 ? '<media-captions-menu hidden></media-captions-menu>' : ''}\n ${controls.playbackRate ? `<media-playback-rate-menu rates=\"${this.controller.config.playbackRates.join(' ')}\" hidden></media-playback-rate-menu>` : ''}\n </slot>\n </media-controller>\n ${showToolbar ? `<div class=\"toolbar\">\n ${controls.navigation ? `<div class=\"group\">\n <button type=\"button\" data-action=\"previous\" ${canvas.index === 0 ? 'disabled' : ''} aria-label=\"${escapeHtml(ui.previousSection)}\">← ${escapeHtml(ui.previous)}</button>\n <button type=\"button\" data-action=\"next\" ${canvas.index === (manifest?.canvases.length ?? 1) - 1 && !this.controller.state.repeat ? 'disabled' : ''} aria-label=\"${escapeHtml(ui.nextSection)}\">${escapeHtml(ui.next)} →</button>\n </div>` : ''}\n ${showSourceSelector || controls.autoAdvance ? `<div class=\"group\">\n ${showSourceSelector ? `<label><span class=\"sr-only\">${escapeHtml(ui.mediaSource)}</span><select data-action=\"source\">${canvas.sources.map((item, index) => `<option value=\"${index}\" ${index === this.controller.state.sourceIndex ? 'selected' : ''}>${escapeHtml(item.label ?? item.format ?? formatString(ui.sourceNumber, { number: index + 1 }))}</option>`).join('')}</select></label>` : ''}\n ${controls.autoAdvance ? `<label><input type=\"checkbox\" data-action=\"auto-advance\" ${this.controller.state.autoAdvance ? 'checked' : ''}> ${escapeHtml(ui.autoAdvance)}</label>` : ''}\n </div>` : ''}\n </div>` : ''}`;\n }\n\n #mediaHtml(canvas: AVCanvas, source: MediaSource): string {\n const tag = source.isHls ? 'hls-video' : source.kind;\n const sourceUrl = this.#resolvedSourceUrl ?? (this.controller.config.resolveRequest ? '' : source.src);\n const attributes = [\n 'slot=\"media\"',\n sourceUrl ? `src=\"${escapeHtml(sourceUrl)}\"` : '',\n `preload=\"${this.controller.config.preload}\"`,\n this.controller.config.crossorigin ? `crossorigin=\"${this.controller.config.crossorigin}\"` : '',\n source.kind === 'video' && canvas.poster ? `poster=\"${escapeHtml(canvas.poster)}\"` : '',\n `aria-label=\"${escapeHtml(canvas.label)}\"`,\n `data-canvasindex=\"${canvas.index}\"`,\n ].filter(Boolean).join(' ');\n const tracks = canvas.tracks.map((track) => `<track src=\"${escapeHtml(track.src)}\" kind=\"${track.kind}\" label=\"${escapeHtml(track.label)}\" ${track.language ? `srclang=\"${escapeHtml(track.language)}\"` : ''} ${track.default ? 'default' : ''}>`).join('');\n return `<${tag} ${attributes}>${tracks}</${tag}>`;\n }\n\n #bind(): void {\n this.#root.querySelector<HTMLElement>('[data-action=previous]')?.addEventListener('click', () => this.controller.previous({ autoplay: this.controller.state.status === 'playing' }));\n this.#root.querySelector<HTMLElement>('[data-action=next]')?.addEventListener('click', () => this.controller.next({ autoplay: this.controller.state.status === 'playing' }));\n this.#root.querySelector<HTMLSelectElement>('[data-action=source]')?.addEventListener('change', (event) => this.controller.selectSource(Number((event.target as HTMLSelectElement).value)));\n this.#root.querySelector<HTMLInputElement>('[data-action=auto-advance]')?.addEventListener('change', (event) => this.controller.setAutoAdvance((event.target as HTMLInputElement).checked));\n }\n\n async #resolveSource(): Promise<void> {\n if (!this.controller.config.resolveRequest) return;\n const token = ++this.#sourceToken;\n try {\n const url = await this.controller.resolvedSourceUrl();\n if (token !== this.#sourceToken || !url) return;\n this.#resolvedSourceUrl = url;\n this.#root.querySelector('video, audio, hls-video')?.setAttribute('src', url);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n\n async #loadTranscript(): Promise<void> {\n const resource = this.controller.canvas?.transcripts[0];\n if (!resource || !this.controller.config.audioArt.transcript) return;\n const token = ++this.#transcriptToken;\n const options: Parameters<typeof loadTranscript>[1] = {};\n if (this.controller.config.fetch) options.fetch = this.controller.config.fetch;\n if (this.controller.config.requestInit) options.requestInit = this.controller.config.requestInit;\n if (this.controller.config.transcript.showNotes !== undefined) options.showNotes = this.controller.config.transcript.showNotes;\n if (this.controller.config.transcript.showMetadata !== undefined) options.showMetadata = this.controller.config.transcript.showMetadata;\n try {\n const cues = await loadTranscript(resource, options);\n if (token !== this.#transcriptToken) return;\n this.#transcriptCues = cues;\n const art = this.#root.querySelector<HTMLElement>('.audio-art');\n const canvas = this.controller.canvas;\n if (art && canvas && this.controller.source?.kind === 'audio') {\n const text = art.querySelector<HTMLElement>('.audio-art-text');\n if (text) text.innerHTML = audioArtTranscriptHtml(canvas.label, cues, true);\n syncAudioArtTranscript(art, this.controller.state.currentTime);\n }\n } catch (cause) {\n if (token !== this.#transcriptToken) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n}\n\nexport const defineMangoAVPlayer = (tagName = 'mango-av-player'): typeof MangoAVPlayerElement => {\n if (typeof customElements === 'undefined') return MangoAVPlayerElement;\n if (!customElements.get(tagName)) customElements.define(tagName, MangoAVPlayerElement);\n return MangoAVPlayerElement;\n};\n"],"mappings":"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","names":[]}
|
|
@@ -46,6 +46,8 @@ var defaultStrings = {
|
|
|
46
46
|
};
|
|
47
47
|
var defaultConfig = {
|
|
48
48
|
controls: {
|
|
49
|
+
navigation: false,
|
|
50
|
+
autoAdvance: false,
|
|
49
51
|
seek: true,
|
|
50
52
|
volume: true,
|
|
51
53
|
captions: true,
|
|
@@ -71,6 +73,10 @@ var defaultConfig = {
|
|
|
71
73
|
showMetadata: false,
|
|
72
74
|
showSearchMarkers: true
|
|
73
75
|
},
|
|
76
|
+
audioArt: {
|
|
77
|
+
transcript: false,
|
|
78
|
+
visualizer: false
|
|
79
|
+
},
|
|
74
80
|
resume: {
|
|
75
81
|
enabled: false,
|
|
76
82
|
maxItems: 200,
|
|
@@ -409,12 +415,17 @@ var collectSupplementing = (pages, canvasId, languages, ui) => {
|
|
|
409
415
|
return [cue];
|
|
410
416
|
});
|
|
411
417
|
if (cues.length > 0) {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
+
const transcriptId = `${pageId ?? canvasId}/inline-transcript`;
|
|
419
|
+
const existing = transcripts.find((transcript) => transcript.id === transcriptId);
|
|
420
|
+
if (existing?.cues) existing.cues.push(...cues);
|
|
421
|
+
else {
|
|
422
|
+
transcripts.push({
|
|
423
|
+
id: transcriptId,
|
|
424
|
+
label: label(page.label, languages, ui.transcript),
|
|
425
|
+
machineGenerated: false,
|
|
426
|
+
cues
|
|
427
|
+
});
|
|
428
|
+
}
|
|
418
429
|
}
|
|
419
430
|
}
|
|
420
431
|
index += 1;
|
|
@@ -791,7 +802,10 @@ var AVPlayerController = class extends EventTarget {
|
|
|
791
802
|
this.#emitState();
|
|
792
803
|
},
|
|
793
804
|
seeking: () => {
|
|
794
|
-
|
|
805
|
+
const time = this.#toCanvasTime(media.currentTime);
|
|
806
|
+
this.#state.currentTime = time;
|
|
807
|
+
this.#emit("av-seek", { canvasId: this.canvas?.id ?? "", from: this.#lastTime, to: time });
|
|
808
|
+
this.#emitState();
|
|
795
809
|
},
|
|
796
810
|
volumechange: () => {
|
|
797
811
|
this.#state.volume = media.volume;
|
|
@@ -1035,4 +1049,4 @@ export {
|
|
|
1035
1049
|
normalizeManifest,
|
|
1036
1050
|
AVPlayerController
|
|
1037
1051
|
};
|
|
1038
|
-
//# sourceMappingURL=chunk-
|
|
1052
|
+
//# sourceMappingURL=chunk-EV6YN7WV.js.map
|