-
Notifications
You must be signed in to change notification settings - Fork 47.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<video /> attribute needed but not guaranteed by React #10389
Comments
The So I think the current behavior is wrong, because So perhaps a more DOM-truthful and minimal implementation would be to have Then React can take it further and also support a special-property tl;dr IMHO yes, |
I am facing the same issue with Android 4.4, according to new (from a year ago), |
@gaearon This should be an easy fix if you're OK with the direction (making |
Since |
@aweary Any progress on this? |
@aweary Same question here, we need the muted attribute to be passed to the video tag to allow autoplaying on mobile devices. Has there been any progress in this direction? Thank you! |
folks progress on an Issue is generally visible and takes the form of a PR. If you don't see a linked PR or updates on an issue assume there is no more progress. It's unclear what the path forward is for this to me. We don't really have way of saying "sync the attribute once and then use the property" and I don't know that adding said logic is even a good idea... |
@jquense I think I understand your point, but inputs have both Personally, just having |
I'm hesitant to change
We don't support many attributes that aren't actually DOM attributes, but we do have |
yeah the controlling behavior ends up causing so many headaches i wouldn't want to do it again, though i agree that it's the right behavior generally.
I like that idea, tho It's always a slippery slope, what would the SSR behavior if someone specifies |
Yeah, I imagine it would behavior just like |
ya my concern is just that most of the value/defaultValue is special cased through the codebase sort of assuming the pattern will be used just for inputs. I should probably go see how it works tho before worrying about that... |
My assumption is that the one use case for |
It could be just as easy as adding it to this list: react/packages/react-dom/src/shared/DOMProperty.js Lines 305 to 322 in 1c2876d
|
`const { Component } = React class App extends Component { render(, document.querySelector("#main"))` |
In the meantime, if you need to autoplay background videos, try this: import * as React from 'react';
import { Component } from 'react';
export class VideoComponent extends Component {
videoContainer: HTMLDivElement;
componentDidMount() {
const video = document.createElement('video');
video.autoplay = true;
video.loop = true;
video.muted = true; // fixes autoplay in chrome
video.setAttribute('playsinline', 'true'); // fixes autoplay in webkit (ie. mobile safari)
const source = document.createElement('source');
source.src = '/path/to/your/video.mp4';
source.type = 'video/mp4';
video.appendChild(source);
this.videoContainer.appendChild(video);
}
render() {
return (
<div ref={(ref) => { this.videoContainer = ref; }} />
);
}
} Thank you for your consideration. |
Indeed, ended up doing dangerouslySetHTML because React doesn't accept muted. |
https://www.npmjs.com/package/react-html5video this component also seems to expose |
And still this issue persisted |
While muted still doesn't show up as an attribute on the video element. Simply adding the playsInline makes the video play on iOS/Safari and Chrome.
As commented in 6544 this supposedly doesn't work in Chrome Android |
I feel like this is a source of bugs and therefore not really a feature request. Is there any plan to work on this? None of the workarounds feel nice to me. |
Agree with @adjohu, this is a bug, not a feature request. Video elements will not autoplay on in mobile Safari without the |
…manually We set `audio.currentTime` and `audio.muted` manually for the following situation: The default behavior is to autoplay the audio and quote shadow animation. However, the modern browser will block autoplay if the audio is not set to `muted`. (For more information, please see https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide#autoplay_availability) (aftermath: `audio.play()` will return promise rejection) And the unlucky part is that we cannot set `muted` in the `audio` tag due to this known issue (facebook/react#10389). (aftermath: we have to change `muted` attribute by manipulating DOM element) Because of the above issues, we cannot play the audio with sound only if users click the audio button. At the same time, the quote animation works well. (aftermath: audio and shadow animation are not synced) When the users click the audio button, we have to play the audio at the right `currentTime` to catch up the shadow animation. (counting the `currentTime` by ourselves) And this patch handles the above situation.
This absence of
|
Considering Chrome is an evergreen browser and version 70 is over 3 years old, it's probably not worth it to work around this quirk. Current versions are working as expected (see #10389 (comment)) |
@eps1lon no browser is evergreen, despite its marketing claims. Most companies' analytics still have a swath of old Chrome usage. |
@eps1lon you can't for sure consider it as "not worth it". My scenario is I have a website builder (take Ucraft, WordPress, Wix, Webflow, etc...) in which you, as a developer, don't fully control the generated dom (structure). Website designers can drop a video widget/element on the page, and turn on/off some controls/tweaks, like AutoPlay, Mute, Loop, Controls, etc... The website designer turns on AutoPlay (which by the way must turn on the Mute too). To ensure your customer's website works well on all of their customers' devices, we need to have this dom property explicitly there. As I personally faced this issue in real life, in which on an iOS device autoPlay was not working. My workaround was: useEffect(() => {
// autoplay does not work on some browsers if video does not have `muted`
// attribute:
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attr-autoplay
// and reacts ignores muted attribute:
// https://github.com/facebook/react/issues/10389
if (videoRef.current) {
if (mute) {
videoRef.current.setAttribute('muted', '');
} else {
videoRef.current.removeAttribute('muted');
}
}
}, [mute]); |
Sure because that's a subjective statement. But just like we don't work around browser quirks for legacy browsers like IE 11 we might not want to work around browser quirks for unmaintained Chrome versions. Especially if the issue is fixed in later versions. Otherwise everybody has to pay for this workaround even though they don't need to. I think it's completely fine to use your workaround if you need to support older browser versions. Arguing that usage implies the need for a fix is simply not practical considering that there are far fewer browser versions with bug fixes than browser versions without these bug fixes. So this has to be done on a case-by-case basis. The only data point we have so far is #10389 (comment). So if you want to contribute to this issue you might want to start collecting a browser matrix where React needs to explicitly set the |
This patch removes `muted` attribute in `<video>` tag since React does not support it yet. The related issue is facebook/react#10389.
I got to this issue today sure is old, I have been reading the whole day things from 2016 until now |
@johiny Assuming you tested this on iOS, it's a Safari issue not a React issue. This would match my testing as well:
|
@eps1lon I tested it on Chrome 105 and Brave 1.43 both on (Android 10) maybe it has something to do with the manufacturer layer in this case MIUI? |
Might be. When I tested it for Android 12 on my Pixel 4a it was working. But that was with Chrome 103. Can you check https://7b65ib.csb.app/ and tell me which video is auto-playing? |
@eps1lon every single one worked both on Chrome and Brave, I will have to keep testing |
Then there's something off with your specific setup. This demo highlights that this issue is no longer relevant to current React versions. |
yeah, I keep testing and find that something was happening with my video when it tried to start I was getting a "PIPELINE_ERROR_DECODE: video decoder reinitialization failed" error that looks like was a conflict between my video and android codecs, so if anyone is facing similar I recommend put an onError on the video can be really useful to see if something weird is happening and re-encode your video. |
This can be helpful function VideoComponent({ muted }) {
const videoProps = { ...(muted && { muted: true }) };
return <video {...videoProps} />;
} |
Is there a proper solution to this problem? Also, I don't understand what the issue is with stripping out this attribute at all. Is somebody more up-to-date on the topic to tell me what the actual issue is? A ticket since 2016, which many people seem to have a problem with, but got never addressed. |
The solution is to take control of the video element in the dom since React is refusing to handle it properly. Assign a ref and call play() or pause() as needed |
I've just made a ref |
I came up with another possible issue. The const videoRef = useRef(null);
useEffect(() => {
videoRef.current.defaultMuted = true;
}) |
We are come with this solution and it is working for us. But it requires dangerouslySetInnerHTML. <div dangerouslySetInnerHTML={{
__html: function () {
let videoContainer = document.createElement("video");
let source = document.createElement("source");
videoContainer.setAttribute("autoplay", "");
videoContainer.setAttribute("muted", "");
videoContainer.setAttribute("loop", "");
source.src = "VIDEO_URL";
videoContainer.appendChild(source);
return videoContainer.outerHTML;
}()
}}/> |
@eps1lon's example doesn't work in iOS because of the lack of The updated example seems to work fine without any trickery. |
lol |
for typescript / tsx 'use client';
import { ComponentProps, useEffect, useRef } from 'react';
export default function VideoComponent({ muted = true, ...props }: ComponentProps<'video'>) {
const videoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {
const videoEl = videoRef.current;
if (!videoEl) return;
videoEl.muted = muted; // this code
videoEl.defaultMuted = muted; // this code
return () => {};
}, []);
return <video ref={videoRef} {...props} muted={muted} />;
} |
As @gaearon mentioned, React does not guarantee an attribute will be set, so probably this is not a bug.
If I understand well, react will ensure the property is set anyway.
Current behaviour
React renders the html
<video />
element without the attributemuted
when explicitly passed.Demo time

In this pen I made a simple example setting
muted
to the element and obtaining the result below:Actually the property is set well, since the original medial file has an audio track and in the pen result is muted.
The point
I think is most a specific need than the expected behaviour.
From the functionality POV, it is absolutely ok, my Component renders a
<video />
muted as requested and so on.But there are browsers and policies, more specifically related to this issue, Webkit and the New updated one year ago, with some interesting changes for the
<video />
element.The part interested is
So, the specific need is to have the explicit
attribute
to tell the browser that this video could beautoPlay
ed.There's a similar issue
The text was updated successfully, but these errors were encountered: