需求:视频和音频分开播放,视频可以有可以无,音频至少一个,由于音频和视频有时差,需要依据视频进行校准。
思路:用定时器延迟
video.js的视频插件,在点击时间轴时,会执行如下函数:
当是在播放时,点击时间轴:先执行pause(暂停)→seeking(跳转)→canplaythrough(视频加载完成)/play(播放),当网络不佳时,先执行play,后执行canplaythrough,当网络情况好时,先执行后执行canplaythrough。
当是在暂停时,点击时间轴:先执行seeking→canplaythrough
openVideo() {
let that = this;
that.player.reset(); //重置 video
that.player.src([
{
type: "video/mp4",
src: that.videoUrl,
},
]);
that.player.load(); // 每次重复打开视频,都将视频进度条置为0
that.player.play();
this.videoFlag = true;
that.player.on("canplaythrough", () => {
// 视频加载好了,能够不停顿地一直播放时执行函数
// 在视频时间轴上跳转时,加载成功,回调也会执行
console.log("canplaythrough", that.player.currentTime());
that.player.markers.reset(that.markersList); // 视频打点
that.player.markers.updateTime(); // 视频打点
that.seeking(false); // 进入页面,即刻播放音频
that.loadedmetadata = true;
});
that.player.on("play", () => {
// 点击播放按钮时会播放,并且调用play函数时会调用
console.log("play", that.loadedmetadata);
if (that.loadedmetadata && !that.isSeeking) {
// 只在点击播放按钮时会播放
//点击进度条时,不执行回调
that.seeking(false);
}
});
that.player.on("pause", () => {
// 点击暂停按钮时会执行
that.seeking(true);
});
that.player.on("seeking", () => {
that.isSeeking = true;
console.log("seeking");
// that.seeking();
});
}
closeVideo(): void {
// 点击关闭后,防止play回调函数中的音频执行
this.loadedmetadata = false;
this.player.pause(); // 暂停视频时会执行回调去暂停和音频
this.videoFlag = false;
clearTimeout(this.timerSeekingOne); // 清除定时器
clearTimeout(this.timer); // 清除定时器
}
// 主要函数
seeking(isPause?: boolean) {
// 该函数主要是在跳转进度条时,让音频对应跳转
clearTimeout(this.timerSeekingOne); // 每一次执行都清除定时器
let currentTimeVideo = this.player.currentTime();
let audioDomList = document.getElementsByTagName("audio");
console.log(this.audioDiffrentTimeArray);
this.audioDiffrentTimeArray.forEach((audioDiffTimeItem, index) => {
const isTime = Math.abs(audioDiffTimeItem); // 取绝对值
if (currentTimeVideo < isTime && audioDiffTimeItem < 0) {
// 视频先录,并且有差值,音频才延迟播放
const time1 = new Date().getTime();
console.log("循环的item", audioDiffTimeItem, index);
// audioDomList[index]["src"] = null;
audioDomList[index].pause();
// 定时器================ 定时器
if (!isPause) {
// 在延迟段内暂停,禁止计时播放
let diff = (isTime - currentTimeVideo) * 1000;
this.timerSeekingOne = setTimeout(() => {
// 让音频延迟到指定秒数后再播放
console.log(
"定时器=====应该延迟的时间",
isTime - currentTimeVideo,
"s",
"延迟了,音频时间",
new Date().getTime() - time1,
"ms"
);
// audioDomList[index].src = this.audioList[index].fileName;
// audioDomList[index].load(); // 重置音频地址,音频置零
audioDomList[index].currentTime = 0; // 重置音频地址,音频置零
console.log(
"音频的起始时间是多少?",
audioDomList[index]["currentTime"],
index
);
this.playAudio(index); // 播放
}, diff);
} else {
console.log("是暂停", isTime - currentTimeVideo);
}
} else {
// 如果时间差为正,说明音频先录,理想情况是一起录制
// 如果音频后录制,播放已经超过延迟时间
// 所以播放音频时,音频播放时间需要后移
const audioItemStartTime =
currentTimeVideo + this.audioDiffrentTimeArray[index];
audioDomList[index]["currentTime"] = audioItemStartTime;
// audioItemStartTime为负数时,默认取0
if (isPause) {
// 不在延迟段内暂停,直接暂停
this.pauseAudio(index);
} else {
this.playAudio(index);
}
}
});
}
pauseAudio(indexVal?: number) {
let audioDomList = document.getElementsByTagName("audio");
console.log(typeof indexVal);
if (typeof indexVal !== "number") {
this.audioList.forEach((audioItem, index) => {
console.log(audioDomList[index].src);
if (audioDomList[index].src) {
// 如果音频地址存在,则播放
audioDomList[index].pause();
}
});
} else {
audioDomList[indexVal].pause();
}
}
playAudio(indexVal?: number) {
this.timer && clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.isSeeking = false; // 确保是在最后,置空
// 确保在跳转的时候不执行play回调
}, 500);
let audioDomList = document.getElementsByTagName("audio");
if (typeof indexVal !== "number") {
// 如果不是通过跳转时间点进入播放
this.audioList.forEach((audioItem, index) => {
if (audioItem.fileName) {
// 如果音频地址存在,则播放
audioDomList[index].play();
}
});
} else {
audioDomList[indexVal].play();
}
}