Передача JavaScript-кода потокового видео в React (ML5) - PullRequest
0 голосов
/ 03 февраля 2019

Я пытаюсь преобразовать код в примере классификации изображений ML5 ( Ссылка ) в мой компонент React, а именно:

class App extends Component {
  video = document.getElementById('video');

  state = {
    result :null
  }

  loop = (classifier) => {
    classifier.predict()
      .then(results => {
        this.setState({result: results[0].className});
        this.loop(classifier) // Call again to create a loop
      })
  }

  componentDidMount(){
    ml5.imageClassifier('MobileNet', this.video)
      .then(classifier => this.loop(classifier))

  }
  render() {

    navigator.mediaDevices.getUserMedia({ video: true })
      .then((stream) => {
        this.video.srcObject = stream;
        this.video.play();
      })

    return (
      <div className="App">
        <video id="video" width="640" height="480" autoplay></video>
      </div>
    );
  }
}

export default App;

Однако это не работает.Сообщение об ошибке говорит, что Unhandled Rejection (TypeError): Cannot set property 'srcObject' of null.

Я могу себе представить, video = document.getElementById('video');, вероятно, не может захватить элемент по идентификатору.Поэтому я попытался

  class App extends Component {
  video_element = <video id="video" width="640" height="480" autoplay></video>;

  ...

  render() {
    ...
    return (
      <div className="App">
        {video_element}
      </div>
    );
  }
}

, который тоже не работал.Я запутался в том, что будет правильным методом для реализации этого?

Любая помощь приветствуется, спасибо!

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Я отвечаю снова с выделением немного другой проблемы, а не ref.

Существует огромная проблема, которая вызывает ужасное моргание и постоянное невыполнение обещания из-за исключения ..... и это получение пользовательского мультимедиа в методе рендеринга!

Учтите это, каждый раз, когда вы устанавливаете состояние, компонент перерисовывается.У вас есть цикл, который постоянно обновляет состояние компонента, и это обещание продолжает выполняться.

Вам нужно получить пользовательский носитель при монтировании компонента:

componentDidMount() {
  navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
    if (this.video.current) {
      this.video.current.srcObject = stream;
      this.video.current.play();
    }

    ml5.imageClassifier("MobileNet", this.video.current)
       .then(classifier => this.loop(classifier));
  });
}

Ваш метод рендерингатогда намного короче:

render() {
  return (
    <div className="App">
      <video ref={this.video} id="video" width="640" height="480" autoPlay />
    </div>
  )
}
0 голосов
/ 03 февраля 2019

В момент создания экземпляра App элемент видео еще не существует, но document.getElementById запускается, возвращая undefined или null.Вот почему вы получаете:

Cannot set property 'srcObject' of null

Потому что здесь:

this.video.srcObject = stream

this.video равно нулю.

Это неправильный способ сделать это.Вы должны подготовить ссылку на элемент dom, назначить его в качестве реквизита и затем получить доступ к элементу оттуда.Что-то вроде:

class App extends Component {

  video = React.createRef()

  ...

  render() {

    navigator.mediaDevices.getUserMedia({ video: true })
      .then((stream) => {
        if ( this.video.current ) {
          this.video.current.srcObject = stream;
          this.video.current.play();
        }
      })

    return (

      ...

      <video ref={ this.video } 
             id="video" 
             width="640" 
             height="480" 
             autoplay
      />
...