«Я обнаружил, что это вызов .load (), который по какой-то причине его нарушает.»
Не уверен, что происходит, но ... Просто слушать loadedmetadata
- это недостаточно, чтобы нарисовать изображение из видео. Метаданные анализируются, но что, если пиксели еще не декодированы и недоступны для снимка? Это даст вам нежелательный результат.
В приведенном ниже примере я изменил ваш код, чтобы прослушивать событие play
, а затем рисовать видеокадр (ы). Другие идеи могут заключаться в том, чтобы загрузить + приостановить, перейти к предпочтительному времени, а затем нарисовать этот кадр в виде эскиза. ) внутри этой функции. Никакая другая функция не узнает, что означает ваш ctx
, если вы определите его только внутри слушателя событий.
Ваш измененный код для тестирования:
const { useRef, useState } = React;
var videoRef;
var canvasRef;
var sourceRef;
var ctx;
var videoWidth;
var videoHeight;
function Thumbnail()
{
videoRef = useRef();
canvasRef = useRef();
sourceRef = useRef();
const [urlSource, setUrlSource] = useState(null);
function onUploadVideoChange(event)
{
event.persist();
const file = event.target.files[0];
const isAllowed = file.type === 'video/mp4';
if (!isAllowed) { alert('Only mp4 videos are allowed'); }
else
{
videoRef.current.setAttribute('src', URL.createObjectURL(file));
videoRef.current.load();
console.log('src', videoRef.current.src);
videoRef.current.addEventListener('play', handle_media_events );
videoRef.current.addEventListener('loadedmetadata', () => {
const videoLength = videoRef.current.duration;
console.log("onUploadVideoChange -> videoLength", videoLength)
videoWidth = videoRef.current.videoWidth;
console.log("onUploadVideoChange -> videoWidth", videoWidth)
videoHeight = videoRef.current.videoHeight;
console.log("onUploadVideoChange -> videoHeight", videoHeight)
videoRef.current.currentTime = Math.floor(videoLength / 2);
console.log('video', videoRef.current);
ctx = canvasRef.current.getContext('2d');
canvasRef.current.width = videoWidth;
canvasRef.current.height = videoHeight;
});
}
}
return (
<div>
<input ref={videoRef} type="file" id="file" accept="video/mp4" onChange={onUploadVideoChange} />
<video ref={videoRef} controls> <source type="video/mp4" ref={sourceRef} /> </video>
<canvas ref={canvasRef}></canvas>
</div>
)
}
function handle_media_events()
{
if (event.type == "play") //# event can be "play", "pause", "seek", etc
{
//draw_video_Still(); //# for canvas with still image frame
draw_video_Move(); //# for canvas with video motion
}
}
function draw_video_Still()
{
ctx.drawImage(videoRef.current, 0, 0, videoWidth, videoHeight);
}
function draw_video_Move()
{
ctx.drawImage(videoRef.current, 0, 0, videoWidth, videoHeight);
setTimeout( () => { draw_video_Move() }, 40 ); //# draw at every 40 millisecs
}
ReactDOM.render(<Thumbnail/>, document.getElementById("app"));