DPlayer.js版本:1.26.0
问题:播放器由直播模式live:true切换到点播模式live:false,点播视频一般都会有进度条和时间,但是这一切换,进度条和时间并不会显示,试了很多版本都这样,即便你dp.destroy()也没用,怎么解决呢?
let isLive = true;//切换的时候,记得要将这个isLive参数设置为false
初始化播放器之前,添加这一句:document.getElementById('dplayer').className = '';
然后按照常规创建dp播放器,这是我用的代码:
// 初始化DPlayer
let dp = null;
let timeoutDuration = 20000; // 30秒默认超时
let currentVideoURL = null; // 当前视频路径
//let currentVideoURL = 'https://hn.bfvvs.com/play/Le3WBQRe/index.m3u8'; // 当前视频路径
let _type = 'auto';
if (/\.flv/.test(currentVideoURL)) {
_type = 'flv';
}
let isLive = true;
let loadTimeout = null; // 超时定时器
let isVideoReady = false; // 视频是否就绪
let isVideoChecking = null;
let errHTML = `
<h2 class="error-title">视频加载失败</h2>
<p class="error-message" id="errorMessage">无法连接到视频服务器,请检查网络连接或尝试其他视频源。</p>
<button class="btn-retry" id="btn-retry">重新加载视频</button>
`;
// 初始化播放器
function initPlayer (event) {
document.getElementById('errorOverlay').classList.add('active');
if (isVideoChecking) {
document.getElementById('errorOverlay').innerHTML= '<span id="video-checking-info">上一次请求尚未完成...</span>';
return false;
}
else {
document.getElementById('errorOverlay').innerHTML= '<span id="video-checking-info">视频资源检测中...</span>';
}
let ok = true;
checkFlvUrlExists(currentVideoURL)
.then(()=>{
console.log('视频地址有效');
if (/\.mp4/.test(currentVideoURL)) {
isLive = false;
document.getElementById('dplayer').className = '';
}
//console.log(isLive);
if (dp) {
dp.destroy();
console.log('销毁旧播放');
}
document.getElementById('errorOverlay').classList.remove('active');
//加载播放器
dp = new DPlayer({
container: document.getElementById('dplayer'),
autoplay: true,
muted: false,
live: isLive,
screenshot: true,
preload: true,
//volume: 0.5,
mutex: true,
hotkey: true,
video: {
url: currentVideoURL,
//pic: video.poster,
type: _type
},
pluginOptions: {
flv: {
mediaDataSource: {
cors: true,
withCredentials: false
},
config: {
enableWorker: true,
enableStashBuffer: false,
lazyLoad: true,
lazyLoadMaxDuration: 3 * 60,
lazyLoadRecoverDuration: 30,
deferLoadAfterSourceOpen: true
},
},
},
});
dp.on('error', (err) => {
clearTimeout(loadTimeout);
//console.error('视频加载错误', dp.video.error);
//console.log('视频加载错误:', getErrorMessage(err));
});
// 监听播放器事件
dp.on('play', () => {
clearTimeout(loadTimeout);// 清除超时计时器(连接成功)
console.log('已连接');
//const flvPlayer = dp.video.flvPlayer;
});
dp.on('loadstart', () => {
console.log('开始加载...');
//设置超时检测(例如10秒后仍无画面则提示)
loadTimeout = setTimeout(() => {
if (!isVideoReady) {
console.log('加载超时,无画面');
const errorOverlay = document.getElementById('errorOverlay');
errorOverlay.innerHTML = errHTML;
errorOverlay.classList.add('active');
document.getElementById('errorMessage').textContent = '连接超时,可能没有视频推送';
}
}, timeoutDuration);
});
// 监听loadedmetadata事件 - 元数据加载完成(有画面的前提)
dp.on('loadedmetadata', () => {
console.log('视频元数据加载完成');
isVideoReady = true;
// 隐藏错误覆盖层
clearTimeout(loadTimeout);
document.getElementById('errorOverlay').classList.remove('active');
});
dp.on('canplay', () => {
// 清除超时计时器(可以播放)
isVideoReady = true;
// 隐藏错误覆盖层
clearTimeout(loadTimeout);
document.getElementById('errorOverlay').classList.remove('active');
console.log('可以开始播放');
dp.play();
});
})
.catch((e)=> {
ok = false;
console.log(e.message);
clearTimeout(loadTimeout);
const errorOverlay = document.getElementById('errorOverlay');
errorOverlay.innerHTML = errHTML;
errorOverlay.classList.add('active');
document.getElementById('errorMessage').textContent = e.message;
})
.finally(()=> {
isVideoChecking = false;
});
//禁止右键菜单
document.querySelector("#dplayer").oncontextmenu = () => {
document.querySelector(".dplayer-menu").style.display = "none";
document.querySelector(".dplayer-mask").style.display = "none";
return false;
};
}
// 初始化播放器前先检测资源是否存在
function checkFlvUrlExists(url) {
return new Promise((resolve, reject) => {
console.log('检测视频源有效性...');
isVideoChecking = true;
let isFlv = false;
if (/\.flv/.test(currentVideoURL)) {
isFlv = true;
}
const _method = isFlv ? 'HEAD' : 'GET';
const xhr = new XMLHttpRequest();
xhr.open(_method, url); // 使用HEAD请求检测资源是否存在,比GET更轻量
xhr.timeout = 5000; // 5秒超时
// 关键:M3U8用GET时,添加Range头只请求前2字节,减少带宽消耗
if (!isFlv) {
xhr.setRequestHeader('Range', 'bytes=0-1'); // 仅请求资源的第0-1字节(共2字节)
}
xhr.onload = () => {
// 200-299状态码表示成功
if (xhr.status >= 200 && xhr.status < 300) {
resolve(true);
} else if (xhr.status === 404) {
// 明确的404错误
reject(new Error('视频资源不存在 (404)'));
} else {
// 其他错误状态
reject(new Error(`视频资源请求失败 (状态码: ${xhr.status})`));
}
};
xhr.onerror = () => reject(new Error('网络错误,无法连接到服务器'));
xhr.ontimeout = () => reject(new Error('请求超时,请稍后重试'));
xhr.send();
});
}
// 重试加载视频
function retryVideo () {
initPlayer();
}
// 切换视频
function switchVideo(url) {
currentVideoURL = url; //更新当前视频索引
if (dp) {
dp.pause();
}
initPlayer(); //重新初始化播放器
}
if (currentVideoURL) {
initPlayer();
}
$(document).on('click', '.channel-container>ul>li', function () {
if (isVideoChecking) {
document.getElementById('errorOverlay').innerHTML= '<span id="video-checking-info">切换速度太快了, 上一次请求尚未完成...</span>';
return false;
}
const _this = $(this);
const channelid = _this.attr('channelid');
const path = _this.attr('path');
const _name = _this.attr('name');
const _author = _this.attr('author');
const _isLive = _this.attr('isLive');
if (_this.hasClass('on')) {
return false;
}
$('.channel-container>ul>li').removeClass('on');
_this.addClass('on');
//console.log(path);
$('.live-title').html(`${_name} `+(_author != ''?`<span>${_author}</span>`:``));
isLive = _isLive == 1 ? true : false;
//console.log(isLive);
currentVideoURL = path;
switchVideo(currentVideoURL);
});
$(document).on('click', '#btn-retry', function () {
// 隐藏错误覆盖层
document.getElementById('errorOverlay').classList.remove('active');
retryVideo();
});