score:14
There are a few things to understand about the way React components work. Firstly according to the React docs:
The render() function should be pure, meaning that it does not modify component state, it returns the same result each time it's invoked, and it does not directly interact with the browser.
You should move initializing your video element to an alternate lifecycle method like componentDidMount
to ensure that it is only initialized once.
Secondly, you rarely need to interact with the DOM directly. In this case we can use the component's internal state to manage the src attribute for the video stream, ensuring it only updates after the stream has initialized.
Here's an updated component that might work:
var MyComponent = React.createClass({
getInitialState: function(){
return { videoSrc: null }
},
componentDidMount: function(){
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({video: true}, this.handleVideo, this.videoError);
}
},
handleVideo: function(stream) {
// Update the state, triggering the component to re-render with the correct stream
this.setState({ videoSrc: window.URL.createObjectURL(stream) });
},
videoError: function() {
},
render: function() {
return <div>
<video src={this.state.videoSrc} autoPlay="true" />
</div>;
}
});
score:0
You can make use of react-webcam. follow the link below, it already has a "getScreenshot" function which returns the base64 encoded picture of the current frame from the webcam.
https://www.npmjs.com/package/react-webcam
const WebcamCapture = () => {
const webcamRef = React.useRef(null);
const [imgSrc, setimgSrc] = React.useState(null);
const capture = React.useCallback(
() => {
const imageSrc = webcamRef.current.getScreenshot();
setimgSrc(imageSrc);
},
[webcamRef,setimgSrc]
);
return (
<div>
<Webcam
audio={false}
height={720}
ref={webcamRef}
screenshotFormat="image/jpeg"
width={1280}
/>
<button onClick={capture}>Capture photo</button>
{imgSrc && (<img src = {imgSrc}/>) }
</div>
);
};
Happy to help!
score:1
This is AG_HIHI's solution written as functional component. I removed the start button, instead start right away once mouted. Place the AppStreamCam component in you parant react component and it shows your webcam feed. Worked like a charm for me.
import React, {useEffect} from 'react'
const AppStreamCam = () => {
const streamCamVideo = () => {
var constraints = { audio: true, video: { width: 1280, height: 720 } };
navigator.mediaDevices
.getUserMedia(constraints)
.then(function(mediaStream) {
var video = document.querySelector("video");
video.srcObject = mediaStream;
video.onloadedmetadata = function(e) {
video.play();
};
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
}); // always check for errors at the end.
}
useEffect(()=>{
streamCamVideo()
},[])
return (
<div>
<video autoPlay={true} id="videoElement" ></video>
</div>
);
}
export default AppStreamCam
score:2
Your handleVideo
method references video
, but you don't define that variable anywhere handleVideo
can see it. Instead, you define it in render
:
var video = document.querySelector("#videoElement");
So there's your first problem, but it's not your real problem. Your real problem is that in React-land you want to avoid document.anything
(getElementById
, getByTagAndClassName
, querySelector
, etc.). This is because React uses a virtual DOM, and if you aren't careful when you reference actual DOM elements those references can quickly go bad (as the virtual DOM replaces the actual DOM after a render
).
The solution is to use React's own alternative technique: refs
. They're easier to explain by example, so here's your code fixed using refs
:
handleVideo: function(stream) {
// KEY CHANGE #1
this.refs.video.src = window.URL.createObjectURL(stream);
},
render: function() {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({video: true}, this.handleVideo, this.videoError);
}
return <div>
{{/* KEY CHANGE #2 */}}
<video autoplay="true" id="videoElement" ref="video">
</video>
</div>;
In other words, if you add a ref="something"
attribute to any element you return in your render
function, you can reference that element anywhere else in your (React) code by referring to this.refs.something
.
There's also other ways to use refs
(eg. you can pass a function), but that's outside the scope of this question, so I'd just recommend you read up on the React docs for refs
:
https://facebook.github.io/react/docs/refs-and-the-dom.html
EDIT
As Jordan Burnett's answer highlighted, there are other important differences between React and normal JS DOM work. Again, explaining all of them would be outside the scope of this question, but I strongly encourage you to read:
https://facebook.github.io/react/docs/react-component.html
to learn the appropriate methods to override to do DOM-interaction work (eg. binding event handlers on non-React components).
score:3
Some of the code posted in the answer has been deprecated and may no longer work in all browsers.
I have created a new React application which uses the latest syntax.
It is very simple and straightforward. I hope it helps someone :)
class AppStreamCam extends React.Component {
constructor(props) {
super(props);
this.streamCamVideo= this.streamCamVideo.bind(this)
}
streamCamVideo() {
var constraints = { audio: true, video: { width: 1280, height: 720 } };
navigator.mediaDevices
.getUserMedia(constraints)
.then(function(mediaStream) {
var video = document.querySelector("video");
video.srcObject = mediaStream;
video.onloadedmetadata = function(e) {
video.play();
};
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
}); // always check for errors at the end.
}
render() {
return (
<div>
<div id="container">
<video autoPlay={true} id="videoElement" controls></video>
</div>
<br/>
<button onClick={this.streamCamVideo}>Start streaming</button>
</div>
);
}
}
Here's my Medium article about it :
How to create a React application to stream your webcam | Basic, Beginner
If it helped don't forget to clap :)
Finally, here's the github repo of the working example : Basic-WebCam-Streamer
Source: stackoverflow.com
Related Query
- How to stream webcam feed on web page using react js component?
- How do I access data returned from an axios get to display on a web page using react js?
- How to call from C# to CEFSharp that run a web page using react
- How to list 4 products on every page using ant design Pagination component in react js?
- How to upload/browse and display image on web page using Hooks in react js?
- How to start and stop both the webcam stream and microphone in React JSX using WebRTC?
- How to reload page once state or data is changed within a react class using component did mount
- How to render list of users from firestore and display it in a table form on web page using react js?
- How do I make my parent component re-run an api call on page refresh using React Router?
- How to create multiple page app using react
- How to make the whole Card component clickable in Material UI using React JS?
- How do I get an attribute of an element nested in a React component using Jest and/or Enzyme?
- How to declare defaultProps on a React component class using TypeScript?
- How to prevent child component from re-rendering when using React hooks and memo?
- How to submit form component in modal dialogue using antd react component library
- How to show build datetime on my react web app using create-react-app?
- How import object from external JS file in React JS using web pack
- How to unit test a style of a React Component using Jest.js?
- using css modules in react how can I pass a className as a prop to a component
- how to render a react component using ReactDOM Render
- How to pass the match when using render in Route component from react router (v4)
- How to distribute fonts or other static assets with a React component library built using Webpack?
- How to attach drag event handlers to a React component using TypeScript
- How do I load SVGs directly in my React component using webpack?
- How to format time in React SSR rendered page using client time zone?
- How to use jest.spyOn with React function component using Typescript
- How to get a React Component reference to change its class using classList?
- React Redux - How to dispatch an action on componentDidMount when using mapDispatchToProps in a connected component
- How to notify parent component of property change when using react hooks?
- How to wait for complete render of React component in Mocha using Enzyme?
More Query from same tag
- React Search filter (hooks) through a High Order Component not working
- Using backchannel with React Client - Bot framework
- React getting state
- Element obtaining value from input only updating after the second time I press enter. Why is this happening? - ReactJS
- how to customize the Facebook Login Button with ReactJs
- How to add "plus-button" on top right in material-table for react and call my specific function in react
- Can't seem to display image using require or uri on React Native! What am I doing wrong?
- how to convert props content which has html tags html and display it instead of displaying it as string?
- Running a React/Rails app locally
- TypeError: Cannot read properties of null when using Locomotive Scroll with Next.js
- How to display data in a grid manner on React JS?
- Too many re-renders. React limits the number of renders to prevent an infinite loop. Updating state of a functional component inside the render method
- How to use the image constructor in React?
- prevent FlowType to check error in node_modules
- Redirect not working with react router authenticated route
- How to call a function in react js from an external JS File
- Cannot get Signal R working due to cors issue - blocked by cors policy
- React - Type 'number | MutableRefObject<any>' is not assignable to type 'LegacyRef<HTMLElement>'
- Handle Dark mode in Material UI redux
- integrate jquery ui datepicker into React JS
- How to change the background color of MUI Menu Popover of TextField with select property?
- React js - apply Regex in forms
- How to execute a method in component after a async dispatch completes(thunk or action creator)?
- How to display Renew date automatically based on plan selection (Monthly, Yearly) in React.js?
- React Error Handling Fetch Data Venues List
- react setState doesn't work with stream data?
- How to show the first item by default in a dynamic Antd form?
- How to make typesafe-actions work with redux-logic transform?
- React's getDOMNode always return component's root DOM node instead of reffed one
- Erorr with post request