使用 React 更新 HTML5 视频的源 URL

IT技术 javascript html reactjs video
2021-04-18 06:53:16

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

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

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,你可以在这里看到

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

5个回答

快速而肮脏的 awnser:key<Clip>or添加props<video>,例如:

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

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

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

  useEffect(() => {
    if (previousUrl.current === url) {
      return;
    }

    if (videoRef.current) {
      videoRef.current.load();
    }

    previousUrl.current = url;
  }, [url]);

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

解释:视频最初不会改变,因为本质上你只是修改<source>元素,React 知道它<video>应该保持不变,所以它不会在 DOM 上更新它,也不会load为该源触发新事件。load应该为 触发一个新事件<video>

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

我需要使用createRef而不是useRef
2021-05-22 06:53:16
@DanielLizik,那肯定是因为您有一个类组件,对吗?
2021-05-22 06:53:16
不,因为我将视频元素 ref 存储在某些 3rd 方状态库中。with useRef,ref 永远不会改变,所以即使source正确更新 react 继续使用旧的 ref;对我来说,它创建了一个奇怪的错误,视频变黑了,但上一个视频的音频继续播放
2021-05-29 06:53:16

<source />由于某种原因,更改 src似乎不会切换视频。这不是我认为的react问题。大概就是这样<source />也许您必须.load()再次调用该元素。但直接在元素本身上设置它更容易。

请参阅顶部答案的评论:Can I use javascript to dynamic change a video's source?

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

function Clip(props) {
  return (
    <video width="320" height="240" src={props.url} controls autoPlay>
    </video>
  )
}
@ Gundam194 不起作用,因为您没有在构造函数中传递道具。jsfiddle.net/d0exvp02/2虽然更改 src 似乎不会导致视频从新的 url 开始
2021-06-01 06:53:16
@Gundam194 立即查看答案
2021-06-06 06:53:16
当然可以,我的不好,你用渲染上的箭头绑定。那么其他的事情是错误的。发布一个 jsfiddle。不过,您仍然应该在函数上执行此操作
2021-06-07 06:53:16
我尝试使用您的代码,但它也不起作用。我从来没有收到updatePosition未绑定的错误。
2021-06-12 06:53:16

在视频标签的 src 属性中绑定 URL 而不是源标签

<视频自动播放循环静音playsinline="true" webkit-playsinline="true" [src]="videoSrc" type="video/mp4">

将父 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>
          )}

您可以使用 key 属性:

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

如果视频的关键属性发生变化,将重新挂载视频组件