-
+
diff --git a/pages/miniClass/classInfo.vue b/pages/miniClass/classInfo.vue
index 8072250..034efdb 100644
--- a/pages/miniClass/classInfo.vue
+++ b/pages/miniClass/classInfo.vue
@@ -1470,10 +1470,10 @@
// 点击作业或者医案,进入详细介绍
clickTask(item,index) {
// var options = JSON.stringify(item)
- if(this.thisClass.state != '1'){
- this.$commonJS.showToast("当前班级状态不可提交");
- return
- }
+ // if(this.thisClass.state != '1'){
+ // this.$commonJS.showToast("当前班级状态不可提交");
+ // return
+ // }
if (this.tijiaoTitleId == 2) {
// 进入的是心得
uni.navigateTo({
diff --git a/uni_modules/yingbing-video/components/yb-video/yb-video.vue b/uni_modules/yingbing-video/components/yb-video/yb-video.vue
index c4a22fe..47ddf7d 100644
--- a/uni_modules/yingbing-video/components/yb-video/yb-video.vue
+++ b/uni_modules/yingbing-video/components/yb-video/yb-video.vue
@@ -110,6 +110,11 @@
type: Array,
default: () => []
},
+ //是否显示倍速提示
+ showRateTips: {
+ type: Boolean,
+ default: false
+ },
//循环播放
loop: {
type: Boolean,
@@ -260,7 +265,6 @@
created() {
//获取当前运行的平台
this.updateHeight()
- console.log('倍速列表是否是ios YINGBING' + JSON.stringify(this.playbackRates))
},
methods: {
//接收消息
diff --git a/uni_modules/yingbing-video/static/html/dist/yb-player.js b/uni_modules/yingbing-video/static/html/dist/yb-player.js
index 7b4f13a..13481dc 100644
--- a/uni_modules/yingbing-video/static/html/dist/yb-player.js
+++ b/uni_modules/yingbing-video/static/html/dist/yb-player.js
@@ -65,13 +65,18 @@ var YbPlayer = /*#__PURE__*/function () {
this.loop = loop; //是否循环播放
this.muted = muted; //是否静音
this.playbackRate = playbackRate || 1; //默认播放倍速
- console.log('倍速列表' + JSON.stringify(playbackRates))
this.playbackRates = playbackRates && playbackRates.length > 0 ? playbackRates : [{
text: '0.5倍速',
value: 0.5
+ }, {
+ text: '0.75倍速',
+ value: 0.75
}, {
text: '正常倍速',
value: 1
+ }, {
+ text: '1.25倍速',
+ value: 1.25
}, {
text: '1.5倍速',
value: 1.5
@@ -120,6 +125,9 @@ var YbPlayer = /*#__PURE__*/function () {
this._toastTimer = null; //消息隐藏定时器
this._danmuTimer = null; //弹幕定时器
this._seizingTimer = null; //卡死定时器(播放一些直播源的时候,可能会出现卡死无反应的情况,需要做出处理)
+ this._rateTimer = null; //倍速显示定时器
+ this._errorRetryCount = 0; //错误重试次数
+ this._maxErrorRetry = 0; //最大重试次数
this._event = {};
}
//开启全屏按钮
@@ -157,6 +165,7 @@ var YbPlayer = /*#__PURE__*/function () {
this._clearDanmuTimer();
this._clearToastTimer();
this._clearControlsTimer();
+ this._clearRateTimer();
this._removeBackbuttonListener();
this._event = {}; //卸载所有监听事件
if (this.container) {
@@ -226,8 +235,8 @@ var YbPlayer = /*#__PURE__*/function () {
_this2.emit('durationchange', _this2.getDuration());
};
this.video.onloadeddata = function () {
- //非直播时初始化播放时长
- if (_this2.initialTime && !_this2.isLive) _this2.seek(_this2.initialTime);
+ //非直播时初始化播放时长(错误恢复时不执行)
+ if (_this2.initialTime && !_this2.isLive && !_this2._isErrorRecovering) _this2.seek(_this2.initialTime);
_this2.emit('loadeddata', {
duration: _this2.getDuration(),
videoWidth: _this2.video.videoWidth,
@@ -255,12 +264,18 @@ var YbPlayer = /*#__PURE__*/function () {
if (_this2.cm) _this2.cm.setConfig('playbackRate', playbackRate);
_this2.emit('ratechange', playbackRate);
_this2.setInnerHTML('yb-player-header-rate', '倍速x' + playbackRate);
+ _this2._clearRateTimer();
var rateEl = _this2.container.getElementsByClassName('yb-player-rate')[0] || document.createElement('DIV');
if (![1, 1.0].includes(playbackRate)) {
rateEl.setAttribute('class', 'yb-player-rate');
rateEl.innerHTML = "\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t".concat(playbackRate + '倍速播放中', "\n\t\t\t\t");
var wrapperEl = _this2.container.getElementsByClassName('yb-player-wrapper')[0];
if (wrapperEl) wrapperEl.appendChild(rateEl);
+ _this2._rateTimer = window.setTimeout(function () {
+ if (rateEl && rateEl.parentNode) {
+ rateEl.parentNode.removeChild(rateEl);
+ }
+ }, 2000);
} else {
if (rateEl) rateEl.remove();
}
@@ -353,7 +368,6 @@ var YbPlayer = /*#__PURE__*/function () {
};
this.video.onerror = function (e) {
if (e && e.target.error) {
- // 网络问题或其他不可恢复的错误
var code = e.target.error.code;
var errorMsg = '';
switch (code) {
@@ -370,10 +384,26 @@ var YbPlayer = /*#__PURE__*/function () {
errorMsg = '视频源不支持或地址无效';
break;
}
- _this2.showError(errorMsg);
- _this2.unloadVideo();
+ console.log('[video.onerror] 检测到视频错误,错误码:' + code + ', 错误信息:' + errorMsg);
+
+ // 错误码 3 尝试跳过问题区间后继续播放
+ if (code === 3) {
+ _this2._skipErrorAndRetry(errorMsg);
+ } else {
+ // 其他错误直接提示错误信息
+ _this2.showError(errorMsg);
+ _this2.unloadVideo();
+ }
+
+ // emit 错误事件,传递详细的错误信息
+ _this2.emit('error', {
+ code: code,
+ message: errorMsg,
+ error: e
+ });
+ } else {
+ _this2.emit('error', e);
}
- _this2.emit('error', e);
};
//视频长按菜单取消
this.video.oncontextmenu = function (e) {
@@ -410,6 +440,7 @@ var YbPlayer = /*#__PURE__*/function () {
key: "unloadVideo",
value: function unloadVideo() {
this._clearSeizingTimer();
+ this._errorRetryCount = 0; // 重置错误计数
this.unloadCustom();
this.unloadDecoder();
this.unloadPano();
@@ -1430,7 +1461,7 @@ var YbPlayer = /*#__PURE__*/function () {
if (['timeDiffrence', 'disableScroll', 'disableTop', 'disableBottom', 'fontScale'].includes(key)) _this.cm.reset();
}
_this.emit('danmuconfigchange', config); //派发弹幕配置更改事件,以便开发者外部记录
- }, 500);
+ }, 2000);
}
this.showPopup('弹幕设置', div);
}
@@ -2451,7 +2482,14 @@ var YbPlayer = /*#__PURE__*/function () {
value: function hideLoading() {
var div = this.container.getElementsByClassName('yb-player-loading')[0];
if (div) div.remove();
- if (this.video.paused) this.showCenterPlay();else this.hideCenter();
+ // if (this.video.paused) this.showCenterPlay();else this.hideCenter();
+ if (this._isErrorRecovering) {
+ this.hideCenter();
+ } else if (this.video.paused) {
+ this.showCenterPlay();
+ } else {
+ this.hideCenter();
+ }
}
//展示中间播放按钮
}, {
@@ -2561,6 +2599,152 @@ var YbPlayer = /*#__PURE__*/function () {
value: function seek(time) {
if (this.video) this.video.currentTime = time;
}
+ /**
+ * 跳过错误区间并重试播放
+ * @param {String} errorMsg 错误信息
+ */
+ }, {
+ key: "_skipErrorAndRetry",
+ value: function _skipErrorAndRetry(errorMsg) {
+ var _this = this;
+
+ // 检查 video 对象是否存在
+ if (!this.video) {
+ console.log('[错误恢复] video 对象不存在,无法恢复');
+ this.showError(errorMsg);
+ this.unloadVideo();
+ return;
+ }
+
+ // 超过最大重试次数,显示错误并卸载视频
+ if (this._errorRetryCount >= this._maxErrorRetry) {
+ this.showError(errorMsg);
+ this.unloadVideo();
+ return;
+ }
+
+ this._errorRetryCount++;
+
+ // 第 1 次错误静默处理,显示 loading
+ if (this._errorRetryCount === 1) {
+ this.showLoading();
+ }
+
+ // 获取当前播放时间,向后跳过 1 秒(跳过损坏的 GOP 区间)
+ var currentTime = this.video.currentTime || 0;
+ // 确保 currentTime 是有效数字
+ if (isNaN(currentTime) || currentTime < 0) {
+ currentTime = 0;
+ }
+ var duration = this.getDuration() || 0;
+ var skipTime = Math.min(currentTime + 1, duration);
+
+ console.log('[错误恢复] 开始处理,当前时间:' + currentTime + 's, 跳转到:' + skipTime + 's');
+
+ // 关键:保存当前 src,然后重新加载视频来恢复状态
+ // var currentSrc = this.video.currentSrc || this.video.src;
+ console.log('[错误恢复] 重新加载视频...');
+
+ // 保存当前倍速设置
+ var currentPlaybackRate = this.video.playbackRate || 1;
+ console.log('[错误恢复] 保存倍速:' + currentPlaybackRate);
+
+ // 设置标志,告诉 loadeddata 不要执行 seek
+ this._isErrorRecovering = true;
+
+ // 重新设置 src 并加载
+ // this.video.src = currentSrc;
+ this.video.load();
+
+ // 清除之前的定时器(如果有)
+ if (this._errorRecoveryTimer) {
+ clearTimeout(this._errorRecoveryTimer);
+ }
+
+ // 等待元数据加载完成
+ var onLoadedMetadata = function() {
+ // 检查 video 对象是否仍然存在
+ if (!_this.video) {
+ console.log('[错误恢复] loadedmetadata 触发,但 video 对象已不存在');
+ return;
+ }
+
+ console.log('[错误恢复] loadedmetadata 触发,设置 currentTime = ' + skipTime);
+ _this.video.removeEventListener('loadedmetadata', onLoadedMetadata);
+
+ // 清除超时定时器
+ if (_this._errorRecoveryTimer) {
+ clearTimeout(_this._errorRecoveryTimer);
+ }
+
+ // 恢复倍速设置
+ _this.video.playbackRate = currentPlaybackRate;
+ console.log('[错误恢复] 恢复倍速:' + currentPlaybackRate);
+
+ // 设置跳转位置
+ _this.video.currentTime = skipTime;
+
+ // 等待 seek 完成后立即播放
+ var onSeeked = function() {
+ // 检查 video 对象是否仍然存在
+ if (!_this2.video) {
+ console.log('[错误恢复] seeked 触发,但 video 对象已不存在');
+ return;
+ }
+
+ console.log('[错误恢复] seeked 触发,实际位置:' + _this2.video.currentTime);
+ _this2.video.removeEventListener('seeked', onSeeked);
+ _this2.tryPlayAfterSeek(errorMsg);
+ };
+
+ _this.video.addEventListener('seeked', onSeeked);
+ };
+
+ this.video.addEventListener('loadedmetadata', onLoadedMetadata);
+
+ // loadedmetadata 超时处理
+ this._errorRecoveryTimer = setTimeout(function() {
+ console.log('[错误恢复] loadedmetadata 超时,直接尝试播放');
+ if (_this.video) {
+ _this.video.removeEventListener('loadedmetadata', onLoadedMetadata);
+ }
+ _this.tryPlayAfterSeek(errorMsg);
+ }, 5000);
+ }
+
+ // 尝试播放
+ }, {
+ key: "tryPlayAfterSeek",
+ value: function tryPlayAfterSeek(errorMsg) {
+ var _this2 = this;
+
+ console.log('[错误恢复] 准备播放,当前状态:paused=' + this.video.paused + ', readyState=' + this.video.readyState + ', currentTime=' + this.video.currentTime);
+
+ // 直接调用 play(),Promise 会处理缓冲
+ var playPromise = this.video.play();
+ console.log('[错误恢复] play() 已调用');
+
+ if (playPromise && typeof playPromise.then === 'function') {
+ playPromise.then(function() {
+ console.log('[错误恢复] 播放成功!');
+ _this2._errorRetryCount = 0;
+ _this2._isErrorRecovering = false; // 清除错误恢复标志
+ // 清除所有定时器
+ if (_this2._errorRecoveryTimer) {
+ clearTimeout(_this2._errorRecoveryTimer);
+ _this2._errorRecoveryTimer = null;
+ }
+ _this2.hideLoading();
+ }).catch(function(err) {
+ console.log('[错误恢复] 播放失败:', err);
+ _this2._skipErrorAndRetry(errorMsg);
+ });
+ } else {
+ _this2._errorRetryCount = 0;
+ _this2._isErrorRecovering = false;
+ _this2.hideLoading();
+ }
+ }
//播放上一个视频
}, {
key: "prev",
@@ -2962,6 +3146,14 @@ var YbPlayer = /*#__PURE__*/function () {
this._seizingTimer = null;
}
}
+ }, {
+ key: "_clearRateTimer",
+ value: function _clearRateTimer() {
+ if (this._rateTimer) {
+ window.clearTimeout(this._rateTimer);
+ this._rateTimer = null;
+ }
+ }
}, {
key: "_removeBackbuttonListener",
value: function _removeBackbuttonListener() {