【发布时间】:2021-10-30 07:09:09
【问题描述】:
我查看了许多相关文章,但我无法找到一个明确的原因,为什么要在本地执行的视频控制相关功能会导致这种延迟。另外,因为是很久以前写的,所以也有区别。
关键是在<canvas>上绘制2个视频图像。在此过程中,我们创建了控制视频播放、暂停、播放速率和帧间移动的函数。
Load按钮时,视频并不一次加载,如果我运行视频,请执行运行播放速率更改并再次运行,它在视频完成时奇怪地行事。
使用的两个视频都是 4 秒长。是需要优化的代码?还是我写的代码逻辑不对?
我好奇如何最好解决它。
// FPS
const FPS = 1 / 60;
const leftVideo = document.querySelector('#left_video');
const rightVideo = document.querySelector('#right_video');
const leftCanvas = document.querySelector('#left_canvas');
const rightCanvas = document.querySelector('#right_canvas');
leftCanvas.width = 256;
leftCanvas.height = 256;
rightCanvas.width = 256;
rightCanvas.height = 256;
const leftCanvasContext = leftCanvas.getContext('2d');
const rightCanvasContext = rightCanvas.getContext('2d');
const mediaLoadButton = document.querySelector('#media_load');
const mediaPlayButton = document.querySelector('#media_play');
const mediaPauseButton = document.querySelector('#media_pause');
const mediaPreviousFrameButton = document.querySelector('#media_previous_frame');
const mediaNextFrameButton = document.querySelector('#media_next_frame');
const mediaPlaybackRateButton = document.querySelectorAll('.media_playback_rate');
const mediaSeekBar = document.querySelector('#media_seekbar');
const updateVideoTime = () => {
mediaSeekBar.value = leftVideo.currentTime;
mediaSeekBar.style.backgroundSize = (mediaSeekBar.value - mediaSeekBar.min) * 100 / (mediaSeekBar.max - mediaSeekBar.min) + '% 100%';
};
const updateSeekBar = (event) => {
const location = (event.offsetX / mediaSeekBar.offsetWidth) * leftVideo.duration;
leftVideo.currentTime = location;
rightVideo.currentTime = location;
};
const loadVideoFirstFrame = (direction) => {
switch(direction) {
case 'left':
if(!isNaN(leftVideo.duration)) {
leftVideo.currentTime = 0;
}
break;
case 'right':
if(!isNaN(rightVideo.duration)) {
rightVideo.currentTime = 0;
}
break;
}
};
const drawVideoFrame = (direction) => {
switch(direction) {
case 'left':
leftCanvasContext.drawImage(leftVideo, 0, 0, leftCanvas.width, leftCanvas.height);
requestAnimationFrame(() => { drawVideoFrame('left'); });
break;
case 'right':
rightCanvasContext.drawImage(rightVideo, 0, 0, rightCanvas.width, rightCanvas.height);
requestAnimationFrame(() => { drawVideoFrame('right'); });
break;
}
};
let playbackRate = 1.0;
let videoMousedown = false;
mediaLoadButton.addEventListener('click', () => {
loadVideoFirstFrame('left');
loadVideoFirstFrame('right');
mediaSeekBar.min = 0;
mediaSeekBar.max = leftVideo.duration;
leftCanvasContext.drawImage(leftVideo, 0, 0, leftCanvas.width, leftCanvas.height);
rightCanvasContext.drawImage(rightVideo, 0, 0, rightCanvas.width, rightCanvas.height);
});
leftVideo.addEventListener('play', () => {
drawVideoFrame('left');
});
leftVideo.addEventListener('timeupdate', updateVideoTime, false);
leftVideo.addEventListener('ended', () => {
loadVideoFirstFrame('left');
loadVideoFirstFrame('right');
mediaSeekBar.value = 0;
mediaSeekBar.min = 0;
mediaSeekBar.max = leftVideo.duration;
leftCanvasContext.drawImage(leftVideo, 0, 0, leftCanvas.width, leftCanvas.height);
rightCanvasContext.drawImage(rightVideo, 0, 0, rightCanvas.width, rightCanvas.height);
});
rightVideo.addEventListener('play', () => {
drawVideoFrame('right');
});
mediaPlayButton.addEventListener('click', () => {
leftVideo.playbackRate = 0.2;
rightVideo.playbackRate = 0.2;
leftVideo.play();
rightVideo.play();
console.info(`PLAYBACK RATE VALUE : ${parseFloat(playbackRate).toFixed(1)}`);
});
mediaPauseButton.addEventListener('click', () => {
leftVideo.pause();
rightVideo.pause();
});
mediaPreviousFrameButton.addEventListener('click', () => {
leftVideo.currentTime = Math.max(0, leftVideo.currentTime - FPS);
rightVideo.currentTime = Math.max(0, rightVideo.currentTime - FPS);
});
mediaNextFrameButton.addEventListener('click', () => {
leftVideo.currentTime = Math.min(leftVideo.duration, leftVideo.currentTime + FPS);
rightVideo.currentTime = Math.min(rightVideo.duration, rightVideo.currentTime + FPS);
});
mediaSeekBar.addEventListener('click', updateSeekBar);
mediaSeekBar.addEventListener('mousemove', (event) => videoMousedown && updateSeekBar(event));
mediaSeekBar.addEventListener('mousedown', () => videoMousedown = true);
mediaSeekBar.addEventListener('mouseup', () => videoMousedown = false);
mediaPlaybackRateButton.forEach((element) => {
element.addEventListener('click', (event) => {
playbackRate = event.target.innerText;
});
});
<div class="container">
<div class="media-wrapper">
<!-- left video -->
<video id="left_video" src="res/left.mp4"></video>
<!-- right video -->
<video id="right_video" src="res/right.mp4"></video>
<!-- left canvas for left video -->
<canvas id="left_canvas"></canvas>
<!-- right canvas for right video -->
<canvas id="right_canvas"></canvas>
</div>
<div class="media-controller-wrapper">
<input id="media_seekbar" type="range" step="any" value="0" min="0" max="100" onchange="updateVideoTime()"/>
<button id="media_load" type="button">Load</button>
<button id="media_play" type="button">Play</button>
<button id="media_pause" type="button">Pause</button>
<button id="media_previous_frame" type="button">Previous frame</button>
<button id="media_next_frame" type="button">Next frame</button>
<button class="media_playback_rate" type="button">1.0</button>
<button class="media_playback_rate" type="button">0.8</button>
<button class="media_playback_rate" type="button">0.6</button>
<button class="media_playback_rate" type="button">0.4</button>
<button class="media_playback_rate" type="button">0.2</button>
</div>
</div>
【问题讨论】:
-
第 1 步:记得减少帖子的代码。如果您的问题是关于视频,那么您应该能够在删除与视频无关的一切时重现您的问题(例如,没有CSS,没有媒体控制,没有Canvas元素等)。将你的代码变成minimal reproducible example 并强迫自己删除一些东西,直到你只剩下最少的代码几乎总是让你自己找到问题,因为在某些时候你删除了一些东西,问题突然消失了:你只是找到了什么造成的。但如果没有,你现在有完美的代码来发帖了。
-
你为什么使用 querySelector 而不是我?例如,QuerySelectoe 非常适合在列表中查找 .selected。
-
请注意,没有理由坚持使用
getElementById而不是querySelector。这不是性能瓶颈,并且会产生相同的结果(null或 HTMLElement)。唯一的区别是您的字符串是否包含#。 querySelector 和 querySelectorAll 函数不是“用于类”,它们是“用于查询选择器”,包括 id、标记名、类、属性以及有效查询选择器可能包含的所有其他内容,并使用它们代替 getElementById、getElementsByTagName、等等都很好。 -
@Jürgen Fink 我在发帖后看到了你的回答,这就是 +1 的来源……我,干杯。
-
历史。
getElementById987654332querySelector2087654332 @几乎十年,Ququery甚至没有添加QuerySelector,直到jQuery显示了能够通过CSS查询选择器获得更多有用的有用,多年来。 span>
标签: javascript html video html5-video