### Run WebSocket Test Server Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/talk-doc.md Execute this command to start the jessibuca-pro-talk-websocket-test-server. Ensure you have installed dependencies first. ```bash node server.js ``` -------------------------------- ### Install Dependencies for WebSocket Server Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/talk-doc.md Run this command to install the necessary Node.js dependencies for the jessibuca-pro-talk-websocket-test-server. ```bash npm install ``` -------------------------------- ### Starting Playback for Multiple Instances Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/6x6-mse-demo.html Adds a click event listener to the 'play' button to initiate playback for all created JessibucaPro instances. It retrieves URLs from input fields, validates them, and starts playback. The button states are updated to reflect that playback is in progress. ```javascript $player.addEventListener('click', function () { for (let i = 0; i < num; i++) { var id = i + 1; var $playHref = document.getElementById('playUrl' + id); let player = playList[i]; if ($playHref.value) { setTimeout((url) => { console.log(url); const validResult = checkUrlIsValid(url) if (!validResult.result) { notifyError(validResult.msg); return; } player && player.play(url).then(() => { }).catch((e) => { console.error(e); }); }, 0, $playHref.value) } } $player.style.display = 'none'; $pause.style.display = 'inline-block'; $destroy.style.display = 'inline-block'; }, false) ``` -------------------------------- ### Initialize Jessibuca Pro for Playback Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/play-vod-demo-ps.html Initializes the JessibucaPro instance with various playback and decoding configurations. This is the primary setup for VOD playback. ```javascript var $player = document.getElementById('play'); var $playbackPause = document.getElementById('playbackPause'); var $playHref = document.getElementById('playUrl'); var $container = document.getElementById('container'); var $destroy = document.getElementById('destroy'); var $useSIMD = document.getElementById('useSIMD'); var $isFFmpegSIMD = document.getElementById('isFFmpegSIMD'); var $useWCS = document.getElementById('useWCS'); var $useSIMDMThreading = document.getElementById('useSIMDMThreading'); var $demuxUseWorker = document.getElementById('demuxUseWorker'); var $isPs = document.getElementById('isPs'); var $isMute = document.getElementById('isMute'); var $isCacheData = document.getElementById('isCacheData'); var forceNoOffscreen = true; // var jessibuca = null; var isPlaybackPause = false; function create() { const showOperateBtns = true; jessibuca = new JessibucaPro({ playType: 'playbackTF', container: $container, videoBuffer: 0.2, // 缓存时长 decoder: './js/decoder-pro.js', isResize: false, text: "", loadingText: "加载中", debug: true, debugLevel: 'debug', showPerformance: true, isFFmpegSIMD: $isFFmpegSIMD.checked, useMThreading: $useSIMDMThreading.checked, showBandwidth: showOperateBtns, // 显示网速 showPlaybackOperate: showOperateBtns, operateBtns: { fullscreen: showOperateBtns, screenshot: showOperateBtns, play: showOperateBtns, audio: showOperateBtns, zoom: showOperateBtns, performance: showOperateBtns, }, playbackConfig: { showControl: true, showRateBtn: true, rateConfig: [ {label: '0.1倍', value: 0.1}, {label: '0.5倍', value: 0.5}, {label: '正常', value: 1}, {label: '2倍', value: 2}, {label: '4倍', value: 4}, {label: '6倍', value: 6}, {label: '8倍', value: 8}, {label: '10倍', value: 10}, {label: '12倍', value: 12}, {label: '14倍', value: 14}, {label: '16倍', value: 16}, ], useWCS: $useWCS.checked, useMSE: false, useSIMD: $useSIMD.checked, }, muted: $isMute.checked === true, demuxUseWorker: $demuxUseWorker.checked === true, isPs: $isPs.checked === true, isSpecialPlaybackVod: true, specialPlaybackVodCacheStream: $isCacheData.checked === true, }); $player.style.display = 'inline-block'; $playbackPause.style.display = 'none'; $destroy.style.display = 'none'; jessibuca.on(JessibucaPro.EVENTS.playFailedAndPaused, (error) => { jessibuca.showErrorMessageTips('播放异常:' + error); }) jessibuca.on('playbackPreRateChange', (rate) => { jessibuca.forward(rate); }) jessibuca.on('playbackEnd', () => { console.error('playbackEnd: 播放结束'); }) jessibuca.on('playbackSeek', (data) => { jessibuca.setPlaybackStartTime(data.ts); }) } create(); ``` -------------------------------- ### Initialize and Play Video Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/async-demo.html Initializes Jessibuca and starts playback. Handles cases where initialization might be asynchronous. ```javascript en(() => { _create(); play(); }); }); } else { create().then(() => { _create(); play(); }); } ``` -------------------------------- ### startRecord(fileName, fileType) Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/api.md Starts recording the video stream. Allows specifying a filename and file type (webm, mp4). ```APIDOC ## startRecord(fileName, fileType) ### Description Starts recording the video stream. ### Parameters #### Path Parameters - **fileName** (string) - Optional - The name of the recording file. Defaults to a timestamp. - **fileType** (string) - Optional - The format of the recording file. Options: `webm`, `mp4`. Defaults to `webm`. ### Usage ```js jessibuca.startRecord('xxx', 'webm') ``` ``` -------------------------------- ### Start Recording a Stream Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/demo-record-player-webview.html Starts the recording process for a given URL after validating its format. The UI updates to show pause and destroy buttons, and a success message is displayed. ```javascript function play() { var href = $playHref.value; if (href) { const validResult = checkUrlIsValid(href) if (!validResult.result) { notifyError(validResult.msg); return; } $recordHtml.innerHTML = ''; jessibucaRecorder.startRecord(href).then(()=>{ $player.style.display = 'none'; $pause.style.display = 'inline-block'; $destroy.style.display = 'inline-block'; notifySuccess('开始录制'); }); } } ``` -------------------------------- ### recordStart Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/api.md Event triggered when recording starts. ```APIDOC ## recordStart ### Description Event triggered when recording starts. ### Event `recordStart` ### Handler ```javascript jessibuca.on("recordStart", function () { console.log("record start") }) ``` ``` -------------------------------- ### Initialize and Play Video Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/demo-sei-dj.html Initializes the Jessibuca player and starts playback. Handles cases where the player might already be destroyed. ```javascript function create() { if (jessibuca) { jessibuca.destroy(); } jessibuca = new Jessibuca({ container: document.getElementById('player-container'), videoBuffer: 1, isResize: false, isAutoPlay: true, useWCS: $useWCS.checked, useSIMD: $useSIMD.checked, useWASM: $useWASM.checked, useMSE: $useMSE.checked, debug: true, log: true, '.' : "/static/assets/", // useWCS:true, // useSIMD:true, // useWASM:true, // useMSE:true, }); jessibuca.on(Jessibuca.Events.χος_ERROR, (ev) => { console.error('Error:', ev); buca.showErrorMessageTips('播放地址不能为空'); }); } function play() { if (jessibuca) { jessibuca.play($videoUrl.value); } else { create(); jessibuca.play($videoUrl.value); } } ``` -------------------------------- ### Event: start Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/api.md Fires when rendering begins. If screenshots are needed after rendering starts, a delay is recommended as the API cannot directly sense when the画面 is rendered. ```APIDOC ## Event: start ### Description Callback when rendering begins. ### Usage ```js jessibuca.on("start", function () { console.log('start render') // If screenshots are needed after rendering starts, a delay is recommended. setTimeout(function () { jessibuca.screenshot('xxx') }, 1 * 1000) // 1 second delay }) ``` ``` -------------------------------- ### Initialize Jessibuca Player Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/demo-swiper-loop.html Initializes a new JessibucaPro player instance. Configure container, decoder path, and control visibility. The player automatically unmutes on 'start' if it's the initial load. ```javascript var videoView = document.createElement("div"); videoView.className = "swiper-video"; var jessibuca = null; videoView.addEventListener('click', function () { jessibuca && jessibuca.cancelMute(); }, false) function createPlayer() { jessibuca = new JessibucaPro({ container: videoView, decoder: './js/decoder-pro.js', hiddenControl: true,// 隐藏控制条 muted: false,// }); jessibuca.on('start', () => { if (performance.navigation.type === 0) { jessibuca.cancelMute(); } }) } createPlayer(); ``` -------------------------------- ### Start Download (HTTP or WebSocket) Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/download-utils.html Automatically determines the protocol (HTTP or WebSocket) based on the URL and initiates the appropriate download function. Includes URL validation and UI state updates. ```javascript async function startDownload() { const url = urlInput.value.trim(); if (!url) { alert('请输入播放地址'); return; } const checkUrlResult = checkUrlIsValid(url); if (checkUrlResult.result === false) { alert(checkUrlResult.msg); return; } const fmt = getSelectedFormat(); // 重置 chunks = []; totalBytes = 0; lastBytes = 0; downloading = true; startTime = Date.now(); sizeText.textContent = '0 B'; speedText.textContent = '-'; durationText.textContent = '00:00:00'; logList.innerHTML = ''; setUIState('downloading'); const protocol = isWebSocketURL(url) ? 'WebSocket' : 'HTTP'; addLog(`开始下载 [${fmt.label}] (${protocol}): ${url}`, 'info'); if (isWebSocketURL(url)) { await startWsDownload(url); } else { await startHttpDownload(url); } } ``` -------------------------------- ### Initialize JessibucaPro for VOD Playback Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/play-vod-demo-mp4.html Initializes the JessibucaPro player for video-on-demand playback. Configure options like video buffer, decoder path, resizing, and various playback features. Use this when starting a new VOD session. ```javascript var $player = document.getElementById('play'); var $playVodPause = document.getElementById('playVodPause'); var $playHref = document.getElementById('playUrl'); var $container = document.getElementById('container'); var $destroy = document.getElementById('destroy'); var $useMSE = document.getElementById('useMSE'); var $useSIMD = document.getElementById('useSIMD'); var $isFFmpegSIMD = document.getElementById('isFFmpegSIMD'); var $useWCS = document.getElementById('useWCS'); var $useWASM = document.getElementById('useWASM'); var $playVodForward = document.getElementById('playVodForward'); var $playVodBackword = document.getElementById('playVodBackword'); var $isMP4 = document.getElementById('isMP4'); var $useSIMDMThreading = document.getElementById('useSIMDMThreading'); var $playVodMp4UseSrc = document.getElementById('playVodMp4UseSrc'); var $useSThreading = document.getElementById('useSThreading'); var $startTime = document.getElementById('startTime'); var forceNoOffscreen = true; // var jessibuca = null; var isPlayVodPause = false; function create() { const showOperateBtns = true; jessibuca = new JessibucaPro({ playType: 'playVod', container: $container, videoBuffer: 0.2, // 缓存时长 decoder: './js/decoder-pro.js', isResize: false, text: "", loadingText: "加载中", debug: true, debugLevel: 'debug', isFFmpegSIMD: $isFFmpegSIMD.checked === true, useMThreading: $useSIMDMThreading.checked === true, useSThreading: $useSThreading.checked === true, decoderErrorAutoWasm: false, timeout: 10000, // showPerformance: true, showBandwidth: showOperateBtns, // 显示网速 showPlaybackOperate: showOperateBtns, operateBtns: { fullscreen: showOperateBtns, screenshot: showOperateBtns, play: showOperateBtns, audio: showOperateBtns, performance: showOperateBtns, }, playVodMp4UseSrc: $playVodMp4UseSrc.checked, playVodConfig: { showRateBtn: true, startTime: Number($startTime.value), rateConfig: [ {label: '0.1倍', value: 0.1}, {label: '0.5倍', value: 0.5}, {label: '正常', value: 1}, {label: '2倍', value: 2}, {label: '4倍', value: 4}, {label: '6倍', value: 6}, {label: '8倍', value: 8}, {label: '10倍', value: 10}, {label: '12倍', value: 12}, {label: '14倍', value: 14}, {label: '16倍', value: 16}, ], useWCS: $useWCS.checked, useMSE: $useMSE.checked, useSIMD: $useSIMD.checked, }, forceNoOffscreen: forceNoOffscreen, muted: false, isFmp4: $isMP4.checked, }); jessibuca.on('playVodEnded', function () { console.log('playVodEnded'); }) jessibuca.on('playVodRateChange', function (rate) { console.log('playVodRateChange', rate); }) $player.style.display = 'inline-block'; $playVodPause.style.display = 'none'; $destroy.style.display = 'none'; } ``` -------------------------------- ### Initialize Jessibuca Player with Specific Container Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/document.md Initialize the Jessibuca player, specifying the DOM element that will contain the video playback. This is a fundamental step for player setup. ```javascript const jessibuca = new Jessibuca({ container: document.getElementById('your-container') }) ``` -------------------------------- ### Initialize Jessibuca Pro Player for Playback Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/playback-simple-demo-reverse.html Initializes the Jessibuca Pro player with playback-specific configurations, including options for MSE, SIMD decoding, and playback controls. This is used when starting a new playback session. ```javascript var $player = document.getElementById('play'); var $playbackPause = document.getElementById('playbackPause'); var $playHref = document.getElementById('playUrl'); var $container = document.getElementById('container'); var $destroy = document.getElementById('destroy'); var $useSIMD = document.getElementById('useSIMD'); var $isFFmpegSIMD = document.getElementById('isFFmpegSIMD'); var $useSIMDMThreading = document.getElementById('useSIMDMThreading'); var $demuxUseWorker = document.getElementById('demuxUseWorker'); var $isFlv = document.getElementById('isFlv'); var $isMute = document.getElementById('isMute'); var forceNoOffscreen = true; // var jessibuca = null; var isPlaybackPause = false; function create() { const showOperateBtns = true; jessibuca = new JessibucaPro({ playType: 'playbackTF', container: $container, videoBuffer: 0.2, // 缓存时长 decoder: './js/decoder-pro.js', isResize: false, text: "", loadingText: "加载中", debug: true, debugLevel: 'debug', showPerformance: true, isFFmpegSIMD: $isFFmpegSIMD.checked, useMThreading: $useSIMDMThreading.checked, showBandwidth: showOperateBtns, // 显示网速 showPlaybackOperate: showOperateBtns, operateBtns: { fullscreen: showOperateBtns, screenshot: showOperateBtns, play: showOperateBtns, audio: showOperateBtns, zoom: showOperateBtns, performance: showOperateBtns, }, playbackConfig: { showControl: true, showRateBtn: true, rateConfig: [ {label: '0.1倍', value: 0.1}, {label: '0.5倍', value: 0.5}, {label: '正常', value: 1}, {label: '2倍', value: 2}, {label: '4倍', value: 4}, {label: '6倍', value: 6}, {label: '8倍', value: 8}, {label: '10倍', value: 10}, {label: '12倍', value: 12}, {label: '14倍', value: 14}, {label: '16倍', value: 16}, ], useMSE: false, useSIMD: $useSIMD.checked, }, muted: $isMute.checked === true, demuxUseWorker: $demuxUseWorker.checked === true, isFlv: $isFlv.checked === true, isSpecialPlaybackVod: true, }); $player.style.display = 'inline-block'; $playbackPause.style.display = 'none'; $destroy.style.display = 'none'; jessibuca.on(JessibucaPro.EVENTS.playFailedAndPaused, (error) => { jessibuca.showErrorMessageTips('播放异常:' + error); }) jessibuca.on('playbackPreRateChange', (rate) => { jessibuca.forward(rate); }) jessibuca.on('playbackEnd', () => { console.error('playbackEnd: 播放结束'); }) jessibuca.on('playbackSeek', (data) => { jessibuca.setPlaybackStartTime(data.ts); }) } create(); ``` -------------------------------- ### Start HTTP Download with Fetch and ReadableStream Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/download-utils.html Initiates an HTTP download using the Fetch API and ReadableStream. Handles connection, streaming, and errors. Aborts download if the signal is triggered. ```javascript async function startHttpDownload(url) { abortController = new AbortController(); try { const res = await fetch(url, {signal: abortController.signal}); if (!res.ok) { throw new Error(`HTTP ${res.status} ${res.statusText}`); } addLog(`连接成功,HTTP ${res.status}`, 'info'); reader = res.body.getReader(); startTimer(); while (true) { const {done, value} = await reader.read(); if (done) { addLog('流已结束(服务端关闭)', 'info'); break; } chunks.push(value); totalBytes += value.byteLength; } } catch (err) { if (err.name === 'AbortError') { addLog('下载已被用户中止', 'info'); } else { addLog(`下载出错: ${err.message}`, 'info'); } } finally { finishDownload(); } } ``` -------------------------------- ### Initialize DOM Elements and State Variables Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/download-utils.html Initializes references to various HTML elements and declares state variables used throughout the download utility. This setup is crucial for interacting with the user interface and managing download progress. ```javascript const urlInput = document.getElementById('urlInput'); const filenameInput = document.getElementById('filenameInput'); const formatSelect = document.getElementById('formatSelect'); const autoDetectTag = document.getElementById('autoDetectTag'); const btnStart = document.getElementById('btnStart'); const btnStop = document.getElementById('btnStop'); const btnExport = document.getElementById('btnExport'); const statusText = document.getElementById('statusText'); const sizeText = document.getElementById('sizeText'); const speedText = document.getElementById('speedText'); const durationText = document.getElementById('durationText'); const logList = document.getElementById('logList'); let chunks = []; let totalBytes = 0; let lastBytes = 0; let reader = null; let abortController = null; let wsInstance = null; let timerInterval = null; let startTime = null; let downloading = false; ``` -------------------------------- ### GOP Structure Example Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/document.md Illustrates the structure of a Group of Pictures (GOP) in video encoding, showing the arrangement of I, B, and P frames. A GOP starts with an I frame and contains a sequence of frames up to the next I frame. ```shell I B B P B B P B B I ... ``` -------------------------------- ### Initialize Environment Buttons and Tips Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/download-utils.html Sets up UI elements to reflect the current environment (HTTPS/HTTP/Local) and provides relevant tips to the user regarding protocol matching and cross-origin policies. ```javascript function initEnvButtons() { const isHttps = window.location.protocol === 'https:'; const isLocal = isLocalEnvironment(); const envSwitch = document.querySelector('.env-switch'); const btnHttpsEnv = document.getElementById('btnHttps'); const btnHttpEnv = document.getElementById('btnHttp'); document.getElementById('currentEnv').textContent = isHttps ? '当前环境:HTTPS' : '当前环境:HTTP'; let tips = '提示:请确保输入的 URL 协议与当前页面协议匹配,否则会触发跨域错误。'; if (isLocal) { tips = '提示:当前页面处于本地环境(localhost / 127.* / ::1)。\n此环境下可自由使用 HTTP、HTTPS、WS 或 WSS 地址,不受当前页面协议限制。'; envSwitch.style.display = 'none'; } else if (isHttps) { tips += '\n当前页面为 HTTPS 协议,URL 必须使用 HTTPS 或 WSS 协议。'; envSwitch.style.display = 'flex'; btnHttpsEnv.style.display = 'none'; btnHttpEnv.style.display = 'inline-block'; } else { tips += '\n当前页面为 HTTP 协议,URL 必须使用 HTTP 或 WS 协议。'; envSwitch.style.display = 'flex'; btnHttpsEnv.style.display = 'inline-block'; btnHttpEnv.style.display = 'none'; } document.getElementById('currentEnvTips').textContent = tips; if (isLocal) { btnHttpsEnv.style.display = 'non ``` -------------------------------- ### Initialize Jessibuca Player Instance Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/6x7-wcs-demo.html Creates a new JessibucaPro instance with specified configuration options. This includes setting the container, decoder path, buffer settings, and enabling WCS. Use this to set up individual video players. ```javascript var $player = document.getElementById('play'); var $pause = document.getElementById('pause'); var $destroy = document.getElementById('destroy'); var $demuxUseWorker = document.getElementById('demuxUseWorker'); var $mseDecoderUseWorker = document.getElementById('mseDecoderUseWorker'); var $isFlv = document.getElementById('isFlv'); var showOperateBtns = true; // 是否显示按钮 var forceNoOffscreen = true; // // var playList = []; var num = 42; function _create(id, index) { var $container = document.getElementById('container' + id); var jessibuca = new JessibucaPro({ container: $container, decoder: './js/decoder-pro.js', videoBuffer: Number($videoBuffer.value), // 缓存时长 videoBufferDelay: Number($videoBufferDelay.value), // // isResize: false, text: "", loadingText: "加载中", debug: false, debugLevel: "debug", decoderErrorAutoWasm: false, showBandwidth: showOperateBtns, // 显示网速 showPerformance: showOperateBtns, useWCS: true, isFlv: $isFlv.checked === true, controlAutoHide: true, operateBtns: { fullscreen: showOperateBtns, screenshot: showOperateBtns, play: showOperateBtns, audio: showOperateBtns, }, watermarkConfig: { text: { content: 'jessibuca-pro' }, right: 10, top: 10 }, demuxUseWorker: $demuxUseWorker.checked === true, mseDecoderUseWorker: $mseDecoderUseWorker.checked === true, websocketOpenTimeout: 3 + index * 0.5, loadingTimeout: 5 + index * 0.5, }); jessibuca.on(JessibucaPro.EVENTS.playFailedAndPaused, (error) => { jessibuca.showErrorMessageTips('播放异常:' + error); }) jessibuca.on(JessibucaPro.EVENTS.crashLog, (log) => { console.error('crashLog', log) }) playList.push(jessibuca); } ``` -------------------------------- ### Start MSE Stream Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/5x5-mse-demo.html Starts streaming a video using MSE. This function is typically called after the player has been initialized. ```javascript mse.start("mse://192.168.1.100/live/100s.live.flv"); ``` -------------------------------- ### Initialize JessibucaPro Player with Options Source: https://github.com/langhuihui/jessibuca/blob/v3/demo/public/pro/demo-control-menu.html Initializes the JessibucaPro player with a comprehensive set of configuration options. This includes settings for video buffering, decoder paths, rendering modes (canvas, WebGL, WebGPU), decoding methods (MSE, WASM, Webcodecs), and control bar customization. Use this for advanced player setup. ```javascript var $player = document.getElementById('play'); var $pause = document.getElementById('pause'); var $playHref = document.getElementById('playUrl'); var $container = document.getElementById('container'); var $destroy = document.getElementById('destroy'); var $fps = document.querySelector('.fps-inner'); var $useMSE = document.getElementById('useMSE'); var $useSIMD = document.getElementById('useSIMD'); var $useWASM = document.getElementById('useWASM'); var $useWCS = document.getElementById('useWCS'); var $videoBuffer = document.getElementById('videoBuffer'); var $videoBufferDelay = document.getElementById('videoBufferDelay'); var $replay = document.getElementById('replay'); var $renderDom = document.getElementById('renderDom'); var $isUseWebGPU = document.getElementById('isUseWebGPU'); var $demuxUseWorker = document.getElementById('demuxUseWorker'); var $useSIMDMThreading = document.getElementById('useSIMDMThreading'); var $replayUseLastFrameShow = document.getElementById('replayUseLastFrameShow'); var $replayShowLoadingIcon = document.getElementById('replayShowLoadingIcon'); var $mseDecoderUseWorker = document.getElementById('mseDecoderUseWorker'); var $controlAutoHide = document.getElementById('controlAutoHide'); var showOperateBtns = true; // 是否显示按钮 var forceNoOffscreen = true; // // var jessibuca = null; function create(options) { options = options || {} jessibuca = new JessibucaPro({ container: $container, videoBuffer: Number($videoBuffer.value), // 缓存时长 videoBufferDelay: Number($videoBufferDelay.value), // 1000s decoder: './js/decoder-pro.js', isResize: false, text: "", loadingText: "加载中", debug: true, debugLevel: "debug", useMSE: $useMSE.checked === true, decoderErrorAutoWasm: false, useSIMD: $useSIMD.checked === true, useWCS: $useWCS.checked === true, useMThreading: $useSIMDMThreading.checked === true, showBandwidth: showOperateBtns, // 显示网速 showPerformance: showOperateBtns, // 显示性能 operateBtns: { fullscreen: showOperateBtns, screenshot: showOperateBtns, play: showOperateBtns, audio: showOperateBtns, performance: showOperateBtns, quality:showOperateBtns, }, timeout: 10, // // audioEngine: "worklet", qualityConfig: ['线一', '线二', '线三', '线四'], forceNoOffscreen: forceNoOffscreen, isNotMute: false, heartTimeout: 10, ptzClickType: 'mouseDownAndUp', ptzZoomShow: true, ptzMoreArrowShow: true, ptzApertureShow: true, ptzFocusShow: true, useCanvasRender: $renderDom.value === 'canvas', useWebGPU: $isUseWebGPU.value === 'webgpu', useWebCanvas: $isUseWebGPU.value === 'canvas', demuxUseWorker: $demuxUseWorker.checked === true, controlHtml: '