【问题标题】:Updating source URL on HTML5 video with React使用 React 更新 HTML5 视频的源 URL
【发布时间】:2017-05-09 06:02:49
【问题描述】:

我想更新 HTML5 视频元素中的源标签,这样当我单击按钮时,正在播放的内容都会切换到新视频。

我有一个 Clip 组件,它返回一个 HTML5 视频元素,源 URL 通过 props 提供。

function Clip(props) {
  return (
    <video width="320" height="240" controls autoPlay>
      <source src={props.url} />
    </video>
  )
}

我还有一个 Movie 组件,它包含多个 URL,每个 URL 对应于电影的一部分。它还包含一个位置属性,它通过记住当前正在播放的部分来充当迭代器。

class Movie extends Component {
  constructor() {
    super();
    this.state = {
      sections: [
        'https://my-bucket.s3.amazonaws.com/vid1.mp4',
        'https://my-bucket.s3.amazonaws.com/vid2.mp4'
      ],
      position: 0
    };
  }
  render() {
    const sections = this.state.sections
    const position = this.state.position

    return (
      <div>
        {position}
        <Clip url={sections[position]} />
        <button onClick={() => this.updatePosition()}>Next</button>
      </div>
    )
  }
  updatePosition() {
    const position = this.state.position + 1;
    this.setState({ position: position });
  }
}

Movie 组件呈现一个 Clip 组件和一个“下一步”按钮。单击下一步按钮时,我想更新位置属性并使用部分中的下一个 URL 重新呈现 HTML5 视频元素。

截至目前,当我点击 Next 时,HTML5 视频源标签会更新,但该元素会继续播放上一个 URL 中的视频。谁能帮我弄清楚如何重置视频元素?

更新:我创建了一个 JSFiddle,你可以看到 here

更新 2: 更新视频元素的 src 属性有效!

【问题讨论】:

  • 你能提供一个jsfiddle吗?

标签: javascript html reactjs video


【解决方案1】:

又快又脏的遮阳篷:key 属性添加到&lt;Clip&gt;&lt;video&gt;,例如:

function Clip({ url }) {
  return (
    <video key={url}>
      <source src={url} />
    </video>
  );
}

推荐的 awnser: 每当有新 URL 时为视频元素触发 load 事件,例如:

function Clip({ url }) {
  const videoRef = useRef();

  useEffect(() => {    
    videoRef.current?.load();
  }, [url]);

  return (
    <video ref={videoRef}>
      <source src={url} />
    </video>
  );
}

解释:视频最初并没有改变,因为本质上你只是在修改 &lt;source&gt; 元素,React 理解 &lt;video&gt; 应该保持不变,所以它不会更新它DOM 并且不会为该源触发新的 load 事件。应该为&lt;video&gt; 触发一个新的load 事件。

肮脏的答案是有效的,因为当您更改 React 元素的 key 时,React 会理解这是一个全新的元素。然后它会在 DOM 中创建一个新元素,该元素自然会在挂载时触发其自己的加载事件。

【讨论】:

  • 我需要使用createRef 而不是useRef
  • @DanielLizik,那肯定是因为你有一个类组件,对吗?
  • 不,因为我将视频元素 ref 存储在某个第 3 方状态库中。使用useRef,引用永远不会改变,因此即使source 正确更新,react 仍会继续使用旧的引用;对我来说,它产生了一个奇怪的错误,视频变黑了,但上一个视频的音频继续播放
【解决方案2】:

由于某种原因,更改 &lt;source /&gt; 的 src 似乎不会切换视频。我不认为这不是反应问题。可能就是&lt;source /&gt; 的工作原理。也许您必须再次在该元素上调用.load()。但是直接在元素本身上设置它更容易。

查看置顶答案的评论:Can I use javascript to dynamically change a video's source?

您可以直接在元素上设置src

function Clip(props) {
  return (
    <video width="320" height="240" src={props.url} controls autoPlay>
    </video>
  )
}

【讨论】:

  • 我尝试使用您的代码,但也没有用。我从未收到 updatePosition 未绑定错误。
  • 当然可以,我的错,你用渲染上的箭头绑定。那就有别的问题了。发布一个jsfiddle。不过,您仍然应该在函数上执行此操作
  • @Gundam194 这不起作用,因为您没有在构造函数中传递道具。 jsfiddle.net/d0exvp02/2。更改 src 似乎不会导致视频从新网址开始
  • @Gundam194 立即查看答案
【解决方案3】:

将 URL 绑定在 Video 标签的 src 属性中,而不是 Source 标签中

【讨论】:

    【解决方案4】:

    向第二个视频添加父 div
    我的代码:

    {isMobile ? (
                <video
                  autoPlay={true}
                  loop
                  className="moviles"
                  muted
                  playsInline
                  poster="/totto/kids.png"
                >
                  <source src="/totto/losmoviles.webm"></source>
                  <source src="/totto/losmoviles.mp4"></source>
                </video>
              ) : (
                <div>
                  <video
                    autoPlay={true}
                    loop
                    className="moviles2"
                    muted
                    playsInline
                    poster="/totto/portada.jpg"
                  >
                    <source src="/totto/moviles.webm"></source>
                    <source src="/totto/moviles.mp4"></source>
                  </video>
                </div>
              )}
    

    【讨论】:

      【解决方案5】:

      你可以使用key属性:

      <video key={videoUrl} autoPlay width="100%">
        <source src={videoUrl} type="video/mp4"></source>
      </video>
      

      如果视频的key属性发生变化,视频组件会被重新挂载

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-10-24
        • 1970-01-01
        • 2017-05-24
        • 1970-01-01
        • 2016-02-20
        • 2011-07-11
        • 2011-08-07
        相关资源
        最近更新 更多