Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set srcObject on audio element with React

I've been trying to set the src attribute of an audio tag in React, but the track never plays.

playTrack(track) {
    const stream = new MediaStream()
    stream.addTrack(track)
    this.setState(() => ({ stream }))
}

render() {
    return (
        <audio src={this.state.stream || null} controls volume="true" autoPlay />
    )
}

When I check in the chrome debugger it shows that the audio tag has [MediaStream] set as its source, but nothing plays and all the controls remained grayed out.

Doing this instead of setting the state works, but I presume this is highly frowned upon in React.

const audio = document.querySelector('audio')
audio.srcObject = stream
like image 256
Erik Avatar asked Feb 04 '18 00:02

Erik


2 Answers

If storing the stream in the state is not a requirement, then you can update the srcObject property using a ref:

playTrack(track) {
    const stream = new MediaStream()
    stream.addTrack(track)
    this.audio.srcObject = stream;
}

render() {
    return (
        <audio ref={audio => {this.audio = audio}} controls volume="true" autoPlay />
    )
}

If you do need to access the stream from the state you can try this

<audio ref={audio => { audio.srcObject = this.state.stream }} />

The reason src={this.state.stream} doesn't work is because src expects a string that represents the url of the audio resource while this.state.stream is a MediaStream object.

audio.src and audio.srcObject are different properties that expect different value types.

like image 131
FuzzyTree Avatar answered Oct 12 '22 07:10

FuzzyTree


For those who use props and don't like to create function on each render:

constructor(props) {
  super(props)
  this.videoRef = React.createRef()
}

render() {
  return <video ref={this.videoRef}/>
}

componentDidMount() {
  this.updateVideoStream()    
}

componentDidUpdate() {
  this.updateVideoStream()
}

updateVideoStream() {
  if (this.videoRef.current.srcObject !== this.props.stream) {
    this.videoRef.current.srcObject = this.props.stream
  }
}
like image 39
Alexander Danilov Avatar answered Oct 12 '22 05:10

Alexander Danilov