Files
ArtPlayer/packages/artplayer-proxy-mediabunny/src/input.js
T
Harvey Zhao 26841c5b1c feat: enable fullscreenWeb option in Artplayer configuration
feat: add danmuku plugin and i18n setup documentation

- Introduced a new danmuku plugin with multiple run code options in the documentation.
- Added language settings documentation for i18n, including default languages, import instructions, and examples for adding and modifying languages.
- Implemented input handling for media sources in the artplayer-proxy-mediabunny package, supporting various formats including HLS.
- Created m3u8 control functionalities for managing audio and video quality settings in the player.

Update mediabunny.js
2026-05-04 13:22:32 +08:00

121 lines
3.3 KiB
JavaScript

import {
ALL_FORMATS,
BlobSource,
HLS_FORMATS,
Input,
ReadableStreamSource,
UrlSource,
} from 'mediabunny'
const M3U8_RE = /\.m3u8(?:$|[?#])/i
export function isHlsSource(src) {
return typeof src === 'string' && M3U8_RE.test(src)
}
export function normalizeSource(src) {
if (typeof src === 'string')
return new UrlSource(src)
if (src instanceof Blob)
return new BlobSource(src)
if (typeof ReadableStream !== 'undefined' && src instanceof ReadableStream) {
return new ReadableStreamSource(src)
}
return src ?? null
}
export function createInput(src) {
const source = normalizeSource(src)
if (!source)
return null
return new Input({
source,
formats: isHlsSource(src) ? HLS_FORMATS : ALL_FORMATS,
})
}
export async function resolveDuration({ input, videoTrack, audioTrack }) {
const tracks = [videoTrack, audioTrack].filter(Boolean)
const referenceTrack = videoTrack || audioTrack
const isLive = Boolean(referenceTrack && await referenceTrack.isLive())
let duration = Number.NaN
if (tracks.length > 0) {
duration = await input.getDurationFromMetadata(tracks, { skipLiveWait: true })
if (duration === null && !isLive) {
duration = await input.computeDuration(tracks, { skipLiveWait: true })
}
}
return isLive ? Number.POSITIVE_INFINITY : duration ?? Number.NaN
}
export async function selectPlaybackTracks(input, src) {
const videoTrack = await input.getPrimaryVideoTrack()
const audioTrack = videoTrack
? await videoTrack.getPrimaryPairableAudioTrack()
: await input.getPrimaryAudioTrack()
const duration = await resolveDuration({ input, videoTrack, audioTrack })
return {
input,
videoTrack,
audioTrack,
duration,
isLive: Number.isFinite(duration) ? false : Boolean((videoTrack || audioTrack) && await (videoTrack || audioTrack).isLive()),
isHls: isHlsSource(src),
videoMode: isHlsSource(src) ? 'auto' : 'manual',
audioMode: isHlsSource(src) ? 'auto' : 'manual',
}
}
async function getTrackBitrate(track) {
return await track.getAverageBitrate() ?? await track.getBitrate() ?? 0
}
export async function getHlsState(media) {
if (!media?.isHls || !media.input)
return null
const [videoTracks, pairableAudioTracks] = await Promise.all([
media.input.getVideoTracks(),
media.videoTrack
? media.videoTrack.getPairableAudioTracks()
: [],
])
const [levels, audios] = await Promise.all([
Promise.all(videoTracks.map(async (track, index) => ({
id: track.id,
track,
index,
name: await track.getName(),
height: await track.getDisplayHeight(),
bitrate: await getTrackBitrate(track),
}))),
Promise.all(pairableAudioTracks.map(async (track, index) => {
const name = await track.getName()
const language = await track.getLanguageCode()
return {
id: track.id,
track,
index,
name,
lang: language,
language,
bitrate: await getTrackBitrate(track),
}
})),
])
return {
levels,
audios,
currentLevel: media.videoTrack ? levels.find(item => item.id === media.videoTrack.id) ?? null : null,
currentAudio: media.audioTrack ? audios.find(item => item.id === media.audioTrack.id) ?? null : null,
videoMode: media.videoMode ?? 'auto',
audioMode: media.audioMode ?? 'auto',
}
}