我一直在尝试编写一个 React Hook 来处理从用户相机捕获的流式视频到 HTML 视频元素。我无法找到处理初始化和取消初始化相机和 HTML 视频元素的最佳方法。
我尝试在挂钩末尾添加清理功能,但我的尝试最终导致视频反复重新初始化或出现许多其他奇怪的错误。
确实,我正在努力弄清楚如何以及为何调用清理函数。它似乎与正在卸载的组件无关。
另外,我不确定如何最好地销毁视频,尽管这里已经有很多答案,但我不确定是否需要完全删除它。如果它挂在身边也没什么坏处,只有六页。我想我只是想在用户离开页面时停止摄像头流式传输,并在用户返回视频页面时再次启动摄像头流式传输。
相机视频流挂钩
import { useEffect, useState } from 'react';
const initialiseCamera = async() => await
navigator
.mediaDevices
.getUserMedia({audio: false, video: true});
export const useCamera = videoRef => {
const [isCameraInitialised, setIsCameraInitialised] = useState(false);
const [video, setVideo] = useState(null);
const [error, setError] = useState('');
const [playing, setPlaying] = useState(true);
useEffect(() => {
if(video || !videoRef.current) {
return;
}
const videoElement = videoRef.current;
if(videoElement instanceof HTMLVideoElement) {
setVideo(videoRef.current);
}
}, [videoRef, video]);
useEffect(() => {
if(!video || isCameraInitialised || !playing) {
return;
}
initialiseCamera()
.then(stream => {
video.srcObject = stream;
setIsCameraInitialised(true);
})
.catch(e => {
setError(e.message);
setPlaying(false);
});
}, [video, isCameraInitialised, playing]);
useEffect(() => {
const videoElement = videoRef.current;
if(playing) {
videoElement.play();
} else {
videoElement.pause();
}
},[playing, videoRef]);
return [video, isCameraInitialised, playing, setPlaying, error];
};
视频观看
import React, {createRef} from 'react';
import { useCamera } from '../hooks/use-camera';
import { Button } from '@orderandchaos/react-components';
const VideoViewDemo = () => {
const videoRef = createRef();
const [video, isCameraInitialised, running, setPlaying, error] = useCamera(videoRef);
return (
<div>
<video
ref={videoRef}
autoPlay={true}
muted={true}
controls
width={480}
height={270}
/>
<Button
onClick={() => setPlaying(!running)}
ariaLabel='Start/Stop Audio'
>{running ? 'Stop' : 'Start'}</Button>
</div>
);
};
export default VideoViewDemo;