DPlayer的错误提示:视频加载失败,前端debug抓到的错误信息:PIPELINE_ERROR_DECODE: Failed to send audio packet for decoding: {timestamp=142869333 duration=21333 size=428 is_key_frame=1 encrypted=0}。
VideoJS的错误提示是:ERROR: (CODE:3 MEDIA_ERR_DECODE) The media playback was aborted due to a corruption problem or because the media used features your browser did not support.
function initVideo(containerId, path, zlbh, spzlid, rywcqkid) {
var duration = 0.0;//学习时长
var currentTime = Number(new Date());//当前观看时间
var sfytjwczt = false;//是否已提交完成状态
var dplayer = new DPlayer({
container: document.getElementById(containerId),
autoplay: false,
theme: 'red',
loop: false,
lang: 'zh-cn',
screenshot: false,
hotkey: true,
preload: 'auto',
logo: '',
volume: 0.7,
mutex: true, //阻止多个播放器同时播放
video: {
url: path, //视频路径
pic: ctx+"img/xszlmrfm.png", //视频封面
thumbnails: ctx+"img/xszlmrfm.png", //视频缩略图
type: 'auto',
},
});
dplayer.seek('0.01'); //跳转到指定时间位置
dplayer.on('playing', function () {
//console.log("播放 playing");
//间隔两秒则自动隐藏
setTimeout(function(){
//为播放器添加隐藏工具条样式
document.getElementById("dplayer").classList.add("dplayer-hide-controller");
}, 2000);
});
dplayer.on('timeupdate', function () {
//console.log("timeupdate ", currentTime, currentTimeTmp, duration, dplayer.video.currentTime, dplayer.video.duration);
if(duration > dplayer.video.duration * 80 / 100){//观看总时长的80%,才算为已学习
if(!sfytjwczt){
gxxxjl();
gxwcqk();//更新完成情况
sfytjwczt = true;
}
}else{
var currentTimeTmp = Number(new Date());
duration += (currentTimeTmp - currentTime) * 1.0 / 1000;
currentTime = currentTimeTmp;
}
});
// 进行监听
dplayer.on('play', function () {
currentTime = Number(new Date());
//console.log("play", currentTime, dplayer.video.currentTime);
tjxxjl();//点击播放按钮了,添加一次学习记录
});
dplayer.on('error', function () {
debugger
console.log("播放结束", dplayer.video.currentTime);
});
dplayer.on('progress', function () {
localStorage.setItem('video.history.' + spzlid, dplayer.video.currentTime);
});
dplayer.on('seeking', function () {
currentTime = Number(new Date());
//console.log("seeking", currentTime, dplayer.video.currentTime);
});
var prefixXxjl = ctx + "syxt/xxjl";//学习记录的Api
//添加学习记录
function tjxxjl() {
$.ajax({
type: "post",
url: prefixXxjl + "/tjxxjl",
data: {
"zlbh": zlbh
},
success: function(data) {
if (data.code == web_status.SUCCESS) {
}else{
$.modal.alertWarning(data.msg);
}
}
});
}
//更新学习记录
function gxxxjl() {
$.ajax({
type: "post",
url: prefixXxjl + "/gxxxjl",
data: {
"zlbh": zlbh,
"wcxx": 1,//1是完成学习
},
success: function(data) {
if (data.code == web_status.SUCCESS) {
dplayer.notice("恭喜你,已完成此文件资料的学习", 3000);
}else{
$.modal.alertWarning(data.msg);
}
}
});
}
//更新完成情况
function gxwcqk() {
if(rywcqkid == undefined || rywcqkid == null || rywcqkid == ""){
return;
}
$.ajax({
type: "post",
url: ctx + "syxt/wdrw/gxwcqk",
data: {
"rywcqkid": rywcqkid,
"ywc": 1,//1是完成任务
},
success: function(data) {
if (data.code == web_status.SUCCESS) {
}else{
$.modal.alertWarning(data.msg);
}
}
});
}
}
<div class="form-group" id="spzlDiv">
<label class="col-sm-3 control-label">视频资料:</label>
<div class="col-sm-8" style="padding-bottom: 15px;">
<div id="dplayer"></div>
</div>
</div>
<script th:src="@{/js/DPlayer/DPlayer.min.js}"></script>
<script th:src="@{/js/DPlayer/MyDPlayer.js}"></script>
<script th:inline="javascript">
var path = ctx + spzlFileInfo.filePath;
path = path.replace("//", "/");
initVideo('dplayer', path, zlglXskczl.zlbh, zlglXskczl.spzlid, rywcqkid);
</script>
可能是你的音频源有问题,你可以换一个音频再试试
tomcat 配置文件传输大小了吗,
还是视频格式问题
我发现你的播放器的一些事件(如timeupdate)在播放时会被不断触发,而你的代码中会在这个事件中不断执行一些逻辑,比如更新学习时长,更新完成情况,甚至还有设置定时器隐藏工具条。
这些频繁执行的逻辑可能会导致浏览器的性能问题,从而导致视频停止播放。我建议你把这些逻辑的执行频率降低,比如每5秒执行一次,或者只在视频播放结束时执行一次。
除了这些,你可以尝试把播放器的预加载设置为"none",或者把视频的类型设置为"mp4",看看是否能够解决问题。
另外,你可以在浏览器的控制台中查看是否有错误信息
看你的报错信息,比较像视频解码报错了,解码失败,所以就无法继续播放了,建议本地找一个确认没有问题的视频测试一下
终于解决了这个问题,原因是直接给前端的视频地址是文件的全路径,对于文件较大的视频就会出现此问题。
解决办法就是写了一个解析接口,在后台代码中控制文件分段大小。视频地址示例:http://ip:port/****/videoPlayer/video?fileId=6034
服务端接口代码如下:
package com.ruoyi.project.videoPlayer.controller;
import com.google.common.net.HttpHeaders;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.project.system.file.domain.FileInfo;
import com.ruoyi.project.system.file.service.IFileInfoService;
import org.apache.shiro.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
/**
* 视频文件管理Controller
*
* @author
* @date 2022-12-28
*/
@Controller
@RequestMapping("/videoPlayer")
public class VideoPlayerController extends BaseController {
@Autowired
private IFileInfoService fileInfoService;
private static final Logger log = LoggerFactory.getLogger(VideoPlayerController.class);
@GetMapping("/video")
public void video(HttpServletRequest request, HttpServletResponse response, String fileId) {
RandomAccessFile targetFile = null;
OutputStream outputStream = null;
try {
FileInfo fileInfo = fileInfoService.selectFileInfoById(Long.valueOf(fileId));
String filePath = fileInfo.getFilePath();
String fileName = fileInfo.getFileName();
outputStream = response.getOutputStream();
response.reset();
//获取请求头中Range的值
String rangeString = request.getHeader("Range");
String path = RuoYiConfig.getUploadPath() + filePath.replace("/profile/upload", "");
//打开文件
File file = new File(path);
if (file.exists()) {
//使用RandomAccessFile读取文件
targetFile = new RandomAccessFile(file, "r");
long fileLength = targetFile.length();
long requestSize = fileLength;
//分段下载视频
if (StringUtils.hasText(rangeString)) {
//从Range中提取需要获取数据的开始和结束位置
long requestStart = 0, requestEnd = 0;
String[] ranges = rangeString.split("=");
if (ranges.length > 1) {
String[] rangeDatas = ranges[1].split("-");
requestStart = Integer.parseInt(rangeDatas[0]);
if (rangeDatas.length > 1) {
requestEnd = Integer.parseInt(rangeDatas[1]);
}
}
if (requestEnd != 0 && requestEnd > requestStart) {
requestSize = requestEnd - requestStart + 1;
}
//根据协议设置请求头
response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
response.setHeader(HttpHeaders.CONTENT_TYPE, "video/mp4");
if (!StringUtils.hasText(rangeString)) {
response.setHeader(HttpHeaders.CONTENT_LENGTH, fileLength + "");
} else {
long length;
if (requestEnd > 0) {
length = requestEnd - requestStart + 1;
response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
response.setHeader(HttpHeaders.CONTENT_RANGE,
"bytes " + requestStart + "-" + requestEnd + "/" + fileLength);
} else {
length = fileLength - requestStart;
response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
response.setHeader(HttpHeaders.CONTENT_RANGE,
"bytes " + requestStart + "-" + (fileLength - 1) + "/" + fileLength);
}
}
//文段下载视频返回206
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
//设置targetFile,从自定义位置开始读取数据
targetFile.seek(requestStart);
} else {
//如果Range为空则下载整个视频
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName + "");
//设置文件长度
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength));
}
//从磁盘读取数据流返回
// byte[] cache = new byte[1024];//1k缓存
byte[] cache = new byte[1024 * 300];//
log.info("开始读取视频,视频路径==" + path + ";requestSize==" + requestSize);
while (requestSize > 0) {
int len = targetFile.read(cache);
if (requestSize < cache.length) {
outputStream.write(cache, 0, (int) requestSize);
} else {
outputStream.write(cache, 0, len);
if (len < cache.length) {
break;
}
}
requestSize -= cache.length;
log.info("requestSize-=cache.length==" + requestSize + ";视频路径==" + path);
}
log.info("结束视频读取");
}
outputStream.flush();
} catch (
Exception e) {
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
}
}
if (targetFile != null) {
try {
targetFile.close();
} catch (IOException e) {
}
}
}
}
}
使用此接口后,完美解决问题
浏览器播放视频自动停止的问题可能有很多原因。下面是一些可能导致这种情况的原因,以及可能的解决方案:
视频文件本身可能损坏,导致浏览器无法正常播放。在这种情况下,你可以尝试使用其他播放器播放视频,以确定视频文件是否有问题。如果确实有问题,你可以尝试使用一些工具来修复视频文件。
可能是浏览器的缓存问题。你可以尝试清除浏览器的缓存,然后再次尝试播放视频。
还可能是视频文件的格式问题。不同的浏览器对视频文件格式的支持情况可能不同,如果视频文件的格式不被浏览器支持,就可能导致视频播放失败。你可以尝试使用视频转换工具将视频文件转换为浏览器支持的格式,然后再次尝试播放。
视频文件的存储位置也可能是问题的原因。如果视频文件的存储位置不可访问,就会导致视频播放失败。你可以尝试确保视频文件的存储位置是可访问的,并检查视频文件的路径是否正确。
还有可能是网络问题。如果你在使用视频文件时遇到了网络问题,那么就可能导致视频播放失败。你可以尝试检查网络连接是否正常,并检查视频文件是否可以在线播放。
还有可能是浏览器本身的问题。如果你的浏览器是一个老版本的浏览器,可能会出现兼容性问题,导致视频播放失败。你可以尝试更新浏览器或者使用其他浏览器进行尝试。
希望这些建议能帮助你解决浏览器播放视频自动停止的问题。