import Player from '../../packages/xgplayer/src' import HlsPlayer from '../../packages/xgplayer-hls/src' localStorage.setItem('xgd', 1) function defaultOpt() { return { isLive: false, autoplay: false, autoplayMuted: false, retryTimes: 3, retryCount: 3, retryDelay: 1000, loadTimeout: 10000, preloadTime: 10, bufferBehind: 10, maxJumpDistance: 3, startTime: 0 } } var cachedOpt = localStorage.getItem('xg:test:hls:opt') try { cachedOpt = JSON.parse(cachedOpt) } catch (error) { cachedOpt = undefined } var opts = Object.assign({ url: 'https://test-streams.mux.dev/x36xhzz/url_0/193039199_mp4_h264_aac_hd_7.m3u8', }, defaultOpt(), cachedOpt) var testPoint = Number(localStorage.getItem('xg:test:hls:point')) if (isNaN(testPoint)) testPoint = 0 window.onload = function () { var dTestPoint = document.getElementById('test-point') var dTestPointDesc = document.getElementById('test-point-desc') var doPresetUrl = document.getElementById('preset-url') var doUrl = document.getElementById('url') var doIsLive = document.getElementById('is-live') var doAutoplay = document.getElementById('autoplay') var doAutoplayMuted = document.getElementById('autoplay-muted') var doLoadTimeout = document.getElementById('load-timeout') var doRetryCount = document.getElementById('retry-count') var doRetryDelay = document.getElementById('retry-delay') var doFetchOptions = document.getElementById('fetch-options') var doPreloadTime = document.getElementById('preload-time') var doBufferBehind = document.getElementById('buffer-behind') var doMaxJumpDistance = document.getElementById('max-jump-distance') var doStartTime = document.getElementById('start-time') var doTargetLatency = document.getElementById('target-latency') var doMaxLatency = document.getElementById('max-latency') var doDisconnectTime = document.getElementById('disconnect-time') var dbResetOpt = document.getElementById('reset-opt') var dbApplyOpt = document.getElementById('apply-opt') var dbPlay = document.getElementById('play') var dbPause = document.getElementById('pause') var dbReplay = document.getElementById('replay') var dbDestroy = document.getElementById('destroy') var dbSwitchUrl = document.getElementById('switch-url') var dbSetUrl = document.getElementById('set-url') var dbSeek = document.getElementById('seek') var dStreamsContainer = document.getElementById('streams') var dStreamForce = document.getElementById('stream-force') var dVideoStreams = document.getElementById('video-streams') var dAudioStreams = document.getElementById('audio-streams') var dlEvent = document.getElementById('event') var dlError = document.getElementById('error') var dsSpeed = document.getElementById('speed') var dsFrame = document.getElementById('frame') var dsBuffer = document.getElementById('buffer') var dsOption = document.getElementById('option') dTestPoint.selectedIndex = testPoint dsOption.innerHTML = '
' + JSON.stringify(opts, null, 2) + '
' function inp(d) { return d.getElementsByTagName('input')[0] } var player function updateOpts(key, value, type) { if (type === 'object') { try { value = (new Function('x', 'return ' + value))() } catch (error) { } } opts[key] = value localStorage.setItem('xg:test:hls:opt', JSON.stringify(opts)) dsOption.innerHTML = '
' + JSON.stringify(opts, null, 2) + '
' } function resetOpts() { opts = Object.assign({ url: opts.url }, defaultOpt()) localStorage.setItem('xg:test:hls:opt', JSON.stringify(opts)) window.location.reload() } function initPlayer() { if (player) { player.destroy() setTimeout(init, 100) } else { init() } function init() { window.player = player = new Player({ // mediaType: 'live-video', el: document.getElementById('player'), plugins: [HlsPlayer], url: opts.url, isLive: opts.isLive, startTime: opts.startTime, autoplay: opts.autoplay, autoplayMuted: opts.autoplayMuted, hls: Object.assign({}, opts, { fetchOptions: Object.assign({ referrer: 'no-referrer', referrerPolicy: 'no-referrer' }, opts.fetchOptions) }) }); dlEvent.innerHTML = '' dlError.innerHTML = '' function pushEvent(name, value, container) { container = container || dlEvent console.debug('[test]', name, value) if (container === dlEvent && logFilter && !logFilter(name, value)) { return } if (name === 'core.metadataparsed') { if (value.track?.samples?.length > 100) { return { '_': '数据过大,请查看devtools' } } } try { value = JSON.stringify(value) } catch (error) { } var record = document.createElement('div') record.innerHTML = '
' + name + ' / ' + player.video.currentTime + '' + value + '
' container.prepend(record) } player.on('loadstart', function (event) { pushEvent('loadstart', event) }) player.on('loadeddata', function (event) { pushEvent('loadeddata', event) }) player.on('play', function (event) { pushEvent('play', event) }) player.on('pause', function (event) { pushEvent('pause', event) }) player.on('ended', function (event) { pushEvent('ended', event) }) player.on('autoplay_was_prevented', function (event) { pushEvent('autoplay_was_prevented', event) }) player.on('playing', function (event) { pushEvent('playing', event) }) player.on('seeking', function (event) { pushEvent('seeking', event) }) player.on('seeked', function (event) { pushEvent('seeked', event) }) player.on('waiting', function (event) { pushEvent('waiting', event) }) player.on('canplay', function (event) { pushEvent('canplay', event) }) player.on('durationchange', function (event) { pushEvent('durationchange', event) }) player.on('ready', function (event) { pushEvent('ready', event) }) player.on('complete', function (event) { pushEvent('complete', event) }) player.on('urlchange', function (event) { pushEvent('urlchange', event) }) player.on('destroy', function (event) { pushEvent('destroy', event) }) player.on('replay', function (event) { pushEvent('replay', event) }) player.on('retry', function (event) { pushEvent('retry', event) }) player.on('core_event', function (event) { pushEvent(event.eventName, event) }) player.on('error', function (event) { pushEvent(event.errorType, event, dlError) }) dStreamForce.checked = true function refreshStreams() { var hls = player.plugins.hls.core var streams = hls.streams var currentStream = hls.currentStream var streams = hls.streams dStreamsContainer.style.display = 'none' dVideoStreams.innerHTML = '' dAudioStreams.innerHTML = '' if (streams.length > 2) { dStreamsContainer.style.display = 'block' streams.forEach(s => { var texts = [] if (s.width && s.height) texts.push(s.width + 'x' + s.height) if (s.videoCodec) texts.push(s.videoCodec.split('.')[0]) if (s.bitrate) texts.push(Math.round(s.bitrate / 8192) + 'KBs') var button = document.createElement('button') button.setAttribute('class', 'py-1 px-2 mt-1 text-white shadow-md mr-2 ' + (currentStream.id === s.id ? 'bg-red-500' : 'bg-green-500')) button.textContent = texts.join('/') button.onclick = function () { hls.switchStream(s.id, dStreamForce.checked).then(function (s) { if (s && s.segments.length && !hls.isLive) { refreshStreams() } }) } dVideoStreams.appendChild(button) }) } if (currentStream.audioStreams.length > 2) { dStreamsContainer.style.display = 'block' var currentAudio = currentStream.currentAudioStream currentStream.audioStreams.forEach(s => { var texts = [] if (s.name) texts.push(s.name) if (s.lang) texts.push(s.lang) if (s.channels) texts.push(s.channels) var button = document.createElement('button') button.setAttribute('class', 'py-1 px-2 mt-1 text-white shadow-md mr-2 ' + (currentAudio.id === s.id ? 'bg-red-500' : 'bg-green-500')) button.textContent = texts.join('/') button.onclick = function () { hls.switchAudioStream(s.id, dStreamForce.checked).then(function (s) { if (s && s.segments.length && !hls.isLive) { refreshStreams() } }) } dAudioStreams.appendChild(button) }) } } player.on('core_event', function (event) { if (event.eventName === HlsPlayer.EVENT.STREAM_PARSED) { refreshStreams() } }) } } function highlight(d) { d.classList.add('bg-yellow-300') } function show(d, h) { d.style.display = 'block'; if (h) highlight(d) } var logFilter var desc = '' switch (testPoint) { case 0: { show(doAutoplay) show(doAutoplayMuted) show(doLoadTimeout) show(doRetryCount) show(doRetryDelay) show(doFetchOptions) show(doPreloadTime) show(doBufferBehind) show(doMaxJumpDistance) show(doStartTime) show(doTargetLatency) show(doMaxLatency) show(doDisconnectTime) } break; case 1: { desc = '设置高亮三个参数。
查看"开发者工具"的Network面板是否进行相应次数的重试
查看“日志”是否触发相应次数的重试事件“core.loadretry”、请求开始“core.loadstart”和请求完成“core.loadcomplete”' show(doLoadTimeout, true) show(doRetryCount, true) show(doRetryDelay, true) highlight(dlEvent) logFilter = function (name) { return name === 'core.loadretry' || name === 'core.loadcomplete' || name === 'core.loadstart' } } break; case 2: { desc = '设置高亮两个参数,并观察状态区域中的“剩余缓存时长”和“当前时间之前缓存时长”是否与设置的值差不多(允许一定的误差)' show(doPreloadTime, true) show(doBufferBehind, true) highlight(dsBuffer) } break; case 3: { desc = '设置高亮两个参数,观察视频是否自动播放(自动播放失败,点击播放按钮可以正常播放),如果是静音自动播放则必须自动播放成功' show(doAutoplay, true) show(doAutoplayMuted, true) } break; case 4: { desc = '点击 API 方法中的 “切换url” 和 “设置url” 按钮,观察是否切换视频成功,并且可以播放,暂停' dbSwitchUrl.style.background = "rgb(245, 158, 11)" dbSetUrl.style.background = "rgb(245, 158, 11)" } break; case 5: { desc = '设置点播的开始时间参数,查看视频是否在该时间点播放。点击 “seek” 按钮或拖动进度条,进行跳转播放时间,观察是否跳转成功。视频播放结束是否出现重播按钮,点击可以重播,点击重播按钮也可以重播。' show(doStartTime, true) dbReplay.style.background = "rgb(245, 158, 11)" dbSeek.style.background = "rgb(245, 158, 11)" } break; case 6: { desc = '设置该参数,然后在直播中暂停,等待设置该参数差不多的时间,然后点播放按钮,观察直播是否拉流(出现黑屏)。等待小于该时间点播放可以连续播放不会重新拉流(不黑屏)' show(doDisconnectTime, true) } break; } dTestPointDesc.innerHTML = desc inp(doUrl).value = opts.url inp(doIsLive).checked = opts.isLive inp(doAutoplay).checked = opts.autoplay inp(doAutoplayMuted).checked = opts.autoplayMuted inp(doLoadTimeout).value = opts.loadTimeout inp(doRetryCount).value = opts.retryCount inp(doRetryDelay).value = opts.retryDelay inp(doFetchOptions).value = opts.fetchOptions || '' inp(doPreloadTime).value = opts.preloadTime inp(doBufferBehind).value = opts.bufferBehind inp(doMaxJumpDistance).value = opts.maxJumpDistance inp(doStartTime).value = opts.startTime inp(doTargetLatency).value = opts.targetLatency inp(doMaxLatency).value = opts.maxLatency inp(doDisconnectTime).value = opts.disconnectTime inp(doUrl).onchange = function () { updateOpts('url', this.value) } inp(doIsLive).onchange = function () { updateOpts('isLive', this.checked) } inp(doAutoplay).onchange = function () { updateOpts('autoplay', this.checked) } inp(doAutoplayMuted).onchange = function () { updateOpts('autoplayMuted', this.checked) } inp(doLoadTimeout).onchange = function () { updateOpts('loadTimeout', this.value) } inp(doRetryCount).onchange = function () { updateOpts('retryCount', this.value) } inp(doRetryDelay).onchange = function () { updateOpts('retryDelay', this.value) } inp(doFetchOptions).onchange = function () { updateOpts('fetchOptions', this.value, 'object') } inp(doPreloadTime).onchange = function () { updateOpts('preloadTime', this.value) } inp(doBufferBehind).onchange = function () { updateOpts('bufferBehind', this.value) } inp(doMaxJumpDistance).onchange = function () { updateOpts('maxJumpDistance', this.value) } inp(doStartTime).onchange = function () { updateOpts('startTime', this.value) } inp(doTargetLatency).onchange = function () { updateOpts('targetLatency', this.value) } inp(doMaxLatency).onchange = function () { updateOpts('maxLatency', this.value) } inp(doDisconnectTime).onchange = function () { updateOpts('disconnectTime', this.value) } doPresetUrl.getElementsByTagName('select')[0].onchange = function () { if (this.value) { updateOpts('url', this.value) inp(doUrl).value = this.value initPlayer() } } initPlayer() dbResetOpt.onclick = resetOpts dbApplyOpt.onclick = initPlayer dbPlay.onclick = function () { player.play() } dbPause.onclick = function () { player.pause() } dbReplay.onclick = function () { player.replay() } dbDestroy.onclick = function () { player.destroy() } dbSwitchUrl.onclick = function () { var url = window.prompt('设置的 url 地址') if (!url) return var startTime = window.prompt('[点播]开始播放时间点', 0) startTime = Number(startTime) if (isNaN(startTime)) startTime = 0 player.switchURL(url, startTime) } dbSetUrl.onclick = function () { var url = window.prompt('设置的 url 地址') if (url) player.src = url } dbSeek.onclick = function () { var time = window.prompt('设置的跳转到的事件点') if (time == null) return time = Number(time) if (isNaN(time)) return player.seek(time) } dTestPoint.onchange = function () { localStorage.setItem('xg:test:hls:point', this.value) resetOpts() } setTimeout(function () { var lastPlayback = null var fps = 0 var prevTime = 0 setInterval(function () { if (player && player.plugins.hls) { var t = player.currentTime prevTime = t var hls = player.plugins.hls.core var buf = hls.bufferInfo() var pq = hls.playbackQuality() var sp = hls.speedInfo() if (lastPlayback) { fps = Math.round((pq.totalVideoFrames - lastPlayback.totalVideoFrames) / (pq.creationTime - lastPlayback.creationTime) * 1000) } lastPlayback = pq dsBuffer.innerHTML = '

当前时间:' + t + 's

' + '

剩余缓存时长:' + buf.remaining + 's

' + '

当前时间之前缓存时长:' + buf.behind + 's

' + '

总缓存时长:' + buf.length + 's

' + '

buffers:' + JSON.stringify(buf.buffers) + '

' dsFrame.innerHTML = '

总渲染帧数:' + pq.totalVideoFrames + '

' + '

掉帧数量:' + pq.droppedVideoFrames + '

' + '

fps:' + fps + '

' dsSpeed.innerHTML = '

当前速度:' + Math.round(sp.speed / (8 * 1024)) + 'KB/s

' + '

平均速度:' + Math.round(sp.avgSpeed / (8 * 1024)) + 'KB/s

' } }, 1000) }) }