Reputation: 10063
I spent quite a lot of time trying to figure out why video embedded like here:
<video height="256" loop autoplay muted controls id="vid">
<source type="video/mp4" src="video_file.mp4"></source>
<source type="video/ogg" src="video_file.ogg"></source>
</video>
starts playing automatically once the page is loaded in FireFox but cannot do autoplay in Webkit based browsers. This only happened on some random pages. So far I was unable to find the cause. I suspect some unclosed tags or extensive JS created by CMS editors.
Upvotes: 261
Views: 604145
Reputation: 8502
One line:
<video autoplay [muted]="'muted'" loop onloadeddata="event.target.play()">
Upvotes: -1
Reputation: 3166
Well I am writing this answer for people who are still stuck in 2024.
Cases: 1. Everything works fine on chrome but not on safari?
-> Possible solution : Change your battery saver setting to never. It only works in this setting! (Wth safari :/)
2. For chrome even if you have autplay, playsinline and muted
-> Chances are your chrome is still not setting muted to true, you need to do oncanplay -> videoRef.muted=true. whichever frontend frame you are using!
Upvotes: 1
Reputation: 480
Nothing worked on Safari iOS until I added playsinline
attribute to the video.
If you're using react based application it would be playsInline
.
Upvotes: 4
Reputation: 57
Angular 15:
Component:
@ViewChild('videoPlayer') videoPlayer!: ElementRef;
video_playback_error: boolean = false;
...
ngAfterViewInit(): void {
this.ngZone.runOutsideAngular(() => {
this.playVideo();
});
}
playVideo() {
let that = this;
let v = document.createElement('video');
v.id = 'videoElement'
v.src = this.mp4_video_url; // we need this
v.muted = true;
v.autoplay = true;
v.loop = true;
v.preload = 'none';
v.playsInline = true;
v.crossOrigin="anonymous";
v.classList.add("w-full", "desktop-sm:h-[700px]", "h-[calc(95vh-150px)]", "absolute", "top-0", "left-0", "object-cover");
const promise = v.play();
if (promise !== undefined) {
promise.then(function() {
console.log('autoplay started');
that.videoPlayer.nativeElement.appendChild(v);
v.muted = true;
v.autoplay = true;
v.src = that.mp4_video_url;
// Automatic playback started!
}).catch(function(error) {
console.log('autoplay error - attempting to play again in .mp4 | ', error);
v.muted = true;
v.autoplay = true;
v.src = that.mp4_video_url;
let fallback = v.play();
if (fallback !== undefined) {
fallback.then((_: any) => {
console.log('autoplay started');
that.videoPlayer.nativeElement.appendChild(v);
v.muted = true;
v.autoplay = true;
v.src = that.mp4_video_url;
// Autoplay started!
}).catch((error: any) => {
console.log('autoplay failed - falling back to image | ', error)
that.video_playback_error = true;
})
} else {
that.video_playback_error = true;
}
});
} else {
this.video_playback_error = true;
}
}
Template:
<div #videoPlayer class="block"></div>
Upvotes: 0
Reputation: 41
iOS Safari, Safari requires us to add the playsinline attribute.
<video autoplay muted playsinline>
<source src="video.mp4" type="video/mp4" />
</video>
Upvotes: 2
Reputation: 8573
For angular, you'll have to mute it and play it in the ngAfterViewInit()
like the following
<video height="256" loop autoplay muted controls id="vid" #videoRef>
<source type="video/mp4" src="video_file.mp4"></source>
<source type="video/ogg" src="video_file.ogg"></source>
</video>
@ViewChild('videoRef', { static: true }) videoRef!: ElementRef
ngAfterViewInit(): void {
const media = this.videoRef.nativeElement
media.muted = true
media.play()
}
Upvotes: 11
Reputation: 121
<video onload='this.play()' src='the source' autoplay controls></video>
This worked for me.
Upvotes: 2
Reputation: 546
I had a problem when playing a video on Safari on iPhones. Adding the playsinline
attribute in the video
tag can solve this problem, and it works!
<video autoplay muted loop playsinline class="someClass">
<source src="source.mp4" type="video/mp4">
</video>
You will also get this problem on Safari on OSX, in case you get yourself confused about this property playsinline
, here is the explaination.
Mobile browsers,
playsinline
will play the video right where it is instead of the default, which is to open it up fullscreen while it plays.
For the Safari on OSX, as the default websites Auto-Play
option is Stop Media with Sound
, this strategy can also introduce the permission issue.
That's why we need the property muted
.
Upvotes: 16
Reputation: 1315
muted
keyword before autoplay
word, Here some privacy change at April, 2018.Upvotes: 8
Reputation: 141
In React + Chrome, it's better to import the video than give it as src to .
import React from 'react';
import styled from 'styled-components';
import video from './videos.mp4';
const StyledVideo = styled.video`
width: 100%;
height: 100vh;
object-fit: cover;
`
const BackgroundVideo = () => {
return (
<StyledVideo autoPlay loop muted>
<source src={video} type="video/mp4" />
</StyledVideo>
);
}
Remember
Upvotes: 0
Reputation: 51
Angular 10:
<video [muted]="true" [autoplay]="true" [loop]="true">
<source src="/assets/video.mp4" type="video/mp4"/>
</video>
Upvotes: 4
Reputation: 557
var video = document.querySelector('video');
video.muted = true;
video.play()
Only this solution helped me, <video autoplay muted ...>...</video>
didn't work...
Upvotes: 18
Reputation: 31
Try this it is simple and short and it works with my code whereas I have the video full screen and behind other elements I simply use z-index -1;
<video autoplay loop id="myVideo">
Upvotes: 0
Reputation: 5677
I got mine to autoplay by making it muted. I think Google rules won't let chrome auto-play unless it's muted.
<video id="video" controls autoplay muted
border:0px solid black;"
width="300"
height="300">
<source src="~/Videos/Lumen5_CTAS_Home2.mp4"
type="video/mp4" />
Your browser does not support the video tag.
Please download the mp4 plugin to see the CTAS Intro.
</video>
Upvotes: 5
Reputation: 8766
On safari iPhone when battery is low and iPhone is on Low Power Mode it won`t autoplay, even if you have the following attributes: autoplay, loop, muted, playsinline set on your video html tag.
Walk around I found working is to have user gesture event to trigger video play:
document.body.addEventListener("touchstart", function () {
var allVideos = document.querySelectorAll('video');
for (var i = 0; i < allVideos.length; i++) {
allVideos[i].play();
}
},{ once: true });
You can read more about user gesture and Video Policies for iOS in webkit site:
https://webkit.org/blog/6784/new-video-policies-for-ios/
Upvotes: 11
Reputation: 3317
Google just changed their policy for autoplay videos, it has to be
muted
You can check here
so just add muted
<video height="256" loop="true" autoplay="autoplay" controls="controls" id="vid" muted>
<source type="video/mp4" src="video_file.mp4"></source>
<source type="video/ogg" src="video_file.ogg"></source>
</video>
Upvotes: 72
Reputation: 71
Try swapping in
autoPlay
for autoplay
.
It seems to be case sensitive at times. Very bizarre because it worked as autoplay
for me, but only if I included controls
Upvotes: 7
Reputation: 61
Google updated Autoplay Policy. Autoplay only work on mute mode. Check the link https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
Upvotes: 6
Reputation: 1180
Chrome does not allow to auto play video with sound on, so make sure to add muted
attribute to the video
tag like this
<video width="320" height="240" autoplay muted>
<source src="video.mp4" type="video/mp4">
</video>
Upvotes: 26
Reputation: 3369
Spent two hours trying all solutions mentioned above.
This is what finally worked for me:
var vid = document.getElementById("myVideo");
vid.muted = true;
Upvotes: 4
Reputation: 385
Try this:
<video width="320" height="240" autoplay muted>
<source src="video.mp4" type="video/mp4">
</video>
Upvotes: 11
Reputation: 294
We recently addressed a similar issue with an embedded video and found that the autoplay and muted attributes were not sufficient for our implementation.
We added a third "playsinline" attribute to the code and it fixed the issue for iOS users.
This fix is specific to videos that are to be played inline. From https://webkit.org/blog/6784/new-video-policies-for-ios/ :
On iPhone, elements will now be allowed to play inline, and will not automatically enter fullscreen mode when playback begins. elements without playsinline attributes will continue to require fullscreen mode for playback on iPhone. When exiting fullscreen with a pinch gesture, elements without playsinline will continue to play inline.
Upvotes: 6
Reputation: 10063
The best fix I could get was adding this code just after the </video>
<script>
document.getElementById('vid').play();
</script>
...not pretty but somehow works.
UPDATE
Recently many browsers can only autoplay the videos with sound off, so you'll need to add muted
attribute to the video tag too
<video autoplay muted>
...
</video>
Upvotes: 540
Reputation: 41
This is because of now chrome is preventing auto play in html5 video, so by default they will not allow auto play. so we can change this settings using chrome flag settings. this is not possible for normal case so i have find another solution. this is working perfect... (add preload="auto")
<video autoplay preload="auto" loop="loop" muted="muted" id="videoBanner" class="videoBanner">
<source src="banner-video.webm" type="video/webm">
<source src="banner-video.mp4" type="video/mp4">
<source src="banner-video.ogg" type="video/ogg">
var herovide = document.getElementById('videoBanner');
herovide.autoplay=true;
herovide.load();
Upvotes: 3
Reputation: 383
For me the issue was that the muted
attribute needed to be added within the video
tag. I.e.:
<video width="1920" height="1980" src="video/Night.mp4"
type="video/mp4" frameborder="0" allowfullscreen autoplay loop
muted></video>`
Upvotes: 32
Reputation: 530
I solved the same problem with,
$(window).on('pageshow',function(){
var vids = document.querySelectorAll('video');
for (var i = 0; i < vids.length;){
vids[i].play();
}
})
You have to launch the videos after the page has been shown.
Upvotes: 1
Reputation: 4475
After using jQuery play()
or DOM maniupulation as suggested by the other answers, it was not still working (Video wasn't autoplaying) in the Chrome for Android (Version 56.0).
As per this post in developers.google.com, From Chrome 53, the autoplay option is respected by the browser, if the video is muted.
So using autoplay muted
attributes in video tag enables the video to be autoplayed in Chrome browsers from version 53.
Excerpt from the above link:
Muted autoplay for video is supported by Chrome for Android as of version 53. Playback will start automatically for a video element once it comes into view if both
autoplay
andmuted
are set[...]<video autoplay muted> <source src="video.webm" type="video/webm" /> <source src="video.mp4" type="video/mp4" /> </video>
- Muted autoplay is supported by Safari on iOS 10 and later.
- Autoplay, whether muted or not, is already supported on Android by Firefox and UC Browser: they do not block any kind of autoplay.
Upvotes: 128
Reputation: 12818
I started out with playing all the visible videos, but old phones weren't performing well. So right now I play the one video that's closest to the center of the window and pause the rest. Vanilla JS. You can pick which algorithm you prefer.
//slowLooper(playAllVisibleVideos);
slowLooper(playVideoClosestToCenter);
function isVideoPlaying(elem) {
if (elem.paused || elem.ended || elem.readyState < 2) {
return false;
} else {
return true;
}
}
function isScrolledIntoView(el) {
var elementTop = el.getBoundingClientRect().top;
var elementBottom = el.getBoundingClientRect().bottom;
var isVisible = elementTop < window.innerHeight && elementBottom >= 0;
return isVisible;
}
function playVideoClosestToCenter() {
var vids = document.querySelectorAll('video');
var smallestDistance = null;
var smallestDistanceI = null;
for (var i = 0; i < vids.length; i++) {
var el = vids[i];
var elementTop = el.getBoundingClientRect().top;
var elementBottom = el.getBoundingClientRect().bottom;
var elementCenter = (elementBottom + elementTop) / 2.0;
var windowCenter = window.innerHeight / 2.0;
var distance = Math.abs(windowCenter - elementCenter);
if (smallestDistance === null || distance < smallestDistance) {
smallestDistance = distance;
smallestDistanceI = i;
}
}
if (smallestDistanceI !== null) {
vids[smallestDistanceI].play();
for (var i = 0; i < vids.length; i++) {
if (i !== smallestDistanceI) {
vids[i].pause();
}
}
}
}
function playAllVisibleVideos(timestamp) {
// This fixes autoplay for safari
var vids = document.querySelectorAll('video');
for (var i = 0; i < vids.length; i++) {
if (isVideoPlaying(vids[i]) && !isScrolledIntoView(vids[i])) {
vids[i].pause();
}
if (!isVideoPlaying(vids[i]) && isScrolledIntoView(vids[i])) {
vids[i].play();
}
}
}
function slowLooper(cb) {
// Throttling requestAnimationFrame to a few fps so we don't waste cpu on this
// We could have listened to scroll+resize+load events which move elements
// but that would have been more complicated.
function repeats() {
cb();
setTimeout(function() {
window.requestAnimationFrame(repeats);
}, 200);
}
repeats();
}
Upvotes: 1
Reputation: 7002
It happens that Safari and Chrome on Desktop do not like DOM manipulation around the video tag. They will not fire the play order when the autoplay attribute is set even if the canplaythrough event has fired when the DOM around the video tag has changed after initial page load. Basically I had the same issue until I deleted a .wrap() jQuery around the video tag and after that it autoplayed as expected.
Upvotes: 34