I have a react application where i am using html5 video tag to show a cover video. It works on ipad, android and all the major browsers but on iphone it just shows a glimpse of a play button which if clicked shows a full page video.
class FrontPage extends React.Component{
constructor(props) {
super(props);
this.authorize = [''];
}
render() {
return (
<div>
<video controls="true" style={BGstyle} preload="yes" autoPlay muted loop width="100%" height="auto">
<source src="/images/film.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
<Ladder/>
<SignUp/>
</div>
);
}
}
var BGstyle = {
position: "absolute",
zIndex:999,
right:0,
bottom:0,
minWidth:'100%',
width: 'auto',
backgroundSize:"cover"
}
export default FrontPage;
you can see it on www.viogto.dk
For iOS 10+
Try the playsinline attribute.
But in camel case for react :
<video playsInline>
Source - New video Policies for iOS
In iOS 8 and iOS 9
Short answer: use iphone-inline-video, it enables inline playback and syncs the audio.
Source - https://stackoverflow.com/a/36348909/3337722
Related
I have a full background HTML5 video autoplaying on the website. Some iOS mobile devices with Safari seem to be having an issue loading the video up, although a majority of times, it's working fine. It erroneously shows the following:
My code is as follows:
const videoDisplay = () => {
let isMobile = {
iOS: function() {
return navigator.userAgent.match(/iPhone|iPad|iPod/i);
},
Android: function() {
return navigator.userAgent.match(/Android/i);
},
BlackBerry: function() {
return navigator.userAgent.match(/BlackBerry/i);
},
Opera: function() {
return navigator.userAgent.match(/Opera Mini/i);
},
Windows: function() {
return navigator.userAgent.match(/IEMobile/i) || navigator.userAgent.match(/WPDesktop/i);
},
any: function() {
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
}
};
if(isMobile.any()) {
return (
<div className="fullscreen-video-wrap">
<video playsInline loop autoPlay muted poster="./media/landingpg_bg.jpg">
<source src={require("./media/video.mp4")} type="video/mp4" />
<source src={require("./media/video.webm")} type="video/webm" />
<source src={require("./media/video.ogv")} type="video/ogg" />
<img src={require("./media/landingpg_bg.jpg")} alt=""/>
Your browser does not support the video tag. I suggest you upgrade your browser.
</video>
</div>
)
} else {
return (
<div className="fullscreen-video-wrap">
<video playsInline loop autoPlay muted poster="./media/landingpg_bg.jpg">
<source src={require("./media/video.mp4")} type="video/mp4" />
<source src={require("./media/video.webm")} type="video/webm" />
<source src={require("./media/video.ogv")} type="video/ogg" />
<img src={require("./media/landingpg_bg.jpg")} alt=""/>
Your browser does not support the video tag. I suggest you upgrade your browser.
</video>
</div>
)
}
}
return (
<div className="v-header">
{videoDisplay()}
<Modal isOpen={modal} setModal={setModal} setFinishModal={setFinishModal} />
<FinishModal isOpen={finishModal} setFinishModal={setFinishModal}/>
<div className="menu">
<animated.img
className={`logo ${(modal || finishModal) && "invisible"}`}
src={require("./media/Renterii_logo_w.png")}
alt="renterii logo"
style={props}
/>
<animated.div
className={`notify ${(modal || finishModal) && "invisible"}`}
onClick={onClickHandler}
style={props2}
>
RENT ITEMS
</animated.div>
<animated.div
className={`social-media ${(modal || finishModal) && "invisible"}`}
style={props3}
>
</animated.div>
</div>
</div>
)
Computer browsers seem to be having no issues with the background video. So far it's been working fine with Firefox, Chrome, and Samsung browsers on mobile devices as well.
I had the same issue with the ios mobile devices and solved it.
As mentioned here : Creating Video for Safari on iPhone: "HTTP servers hosting media files for iOS must support byte-range requests, which iOS uses to perform random access in media playback. (Byte-range support is also known as content-range or partial-range support.) Most, but not all, HTTP 1.1 servers already support byte-range requests."
So you must check whether your server uses byte-range caching or else reconfigure it (I did it with nginx).
PS: Another secondary reason for ios video incompatibility could be the incompatible codecs of each video. The following compression standards are supported:
-H.264 Baseline Profile Level 3.0 video, up to 640 x 480 at 30 fps. Note that B frames are not supported in the Baseline profile.
-MPEG-4 Part 2 video (Simple Profile)
-AAC-LC audio, up to 48 kHz
I want to make the video autoplay without any user gesture in reactjs. I know as per recent google and apple web video policy we cannot autoplay a video having audio without user gesture.But i have seen few websites which still autoplays the video across modern web browsers also.
I came across many questions related to this issue on stackoverflow but none helped me.
Here is what i have tried.
Try 1.
<video id="miniVideo" preLoad="yes" autoPlay="autoplay" loop width="100%" height="auto" playsInline>
<source src="/mini/video/cooper.mp4" type="video/mp4" />
<source src="/mini/video/cooper.webm" type="video/webm" />
</video>
Try 2.
<iframe playsInline id="miniVideo" src="/mini/video/cooper.mp4" width="100%"
height="400px"
allow="autoplay; fullscreen"></iframe>
Try 3.
Script:
componentDidMount(){
var videoTimer = document.getElementById("miniVideo");
videoTimer.play();
}
HTML:
<video id="miniVideo" width="100%" height="100%">
<source src="/video/cooper.mp4" type="video/mp4" />
<p>This browser does not support the video element.</p>
</video>
Your help will be well appreciated.Thanks
I am not sure about Safari but Chrome has changed the autoplay policy. Look here:https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
In order to autoplay, add muted attributed to video tag.
For example:
import React, { Component } from 'react';
class Player extends Component {
constructor(props) {
super(props);
this.state = {
isVideoMuted: true
};
}
handleMuteState = () => {
this.setState(prevState => ({
isVideoMuted: !prevState.isVideoMuted
}));
}
render() {
return (
<div>
<video muted={this.state.isVideoMuted} src="./video.mp4" />
<button onClick={this.handleMuteState}>{this.state.isVideoMuted ? 'Unmute' : 'Mute'}</button >
</div>
);
}
}
export default Player;
I have been searching for a long time and have tried a lot of approaches but nothing seems to be working. I have a video tag which I want to be played when I tap over it. I am working on Ionic 3 and angular. The code is shown below. Please help me out or direct me if I missed anything.
HTML:
<video id="edit-video-element"
width="100%"
[src]="videoPath"
webkit-playsinline
poster="{{thumbnailPath}}" controls autobuffer >
</video>
.ts file
this.video = document.getElementsByTagName('video')[0];
onVideoClick(e) {
(this.video.paused) ? this.video.play() : this.video.pause();
}
Its not displaying any issues, but not working at all.
Update:
<video *ngIf="hasVideo" width="100%" controls autoplay>
<source [src]="videoPath" type="video/mp4">
</video>
I added this and then in the .ts file I have the videoPath as:
file:///private/var/mobile/Containers/Data/Application/99091302-995E-40C7-AF66-0E07BCF09220/tmp/trim.E4AE7B29-06BB-4077-A56A-B546A53267DC.MOV
Update:
I was able to make it work for the files from photo album
I had to install "DomSanitizer" and then add _DomSanitizationService.bypassSecurityTrustUrl(yourFilePath) in my video tag.
Try this out. It's working fine for me.
Html
<video #videoPlayer class="video-player" controls></video>
TS
#ViewChild('videoPlayer') mVideoPlayer: any;
ionViewDidLoad() {
let video = this.mVideoPlayer.nativeElement;
video.src = 'http://techslides.com/demos/sample-videos/small.mp4';
video.play();
}
sass
.video-player {
width: 100%;
height: 100%;
}
I want to start playing a HTML video programmatically from TypeScript when the User clicks on the Video area itself.
This is my HTML code:
<div class="video">
<video controls (click)="toggleVideo()" id="videoPlayer">
<source src="{{videoSource}}" type="video/mp4" />
Browser not supported
</video>
</div>
This is my TypeScript code:
#ViewChild('videoPlayer') videoplayer: any;
toggleVideo(event: any) {
this.videoplayer.play();
}
The issue is that I get an error that says play() function is not defined/exists. What could be the mistake here?
Problem is you're trying to get a reference to video element using its id. You need to use template reference variable (#) instead:
<div class="video">
<video controls (click)="toggleVideo()" #videoPlayer>
<source src="{{videoSource}}" type="video/mp4" />
Browser not supported
</video>
</div>
Read more about template reference variable here.
Edit:
Also, in your toggleVideo(event: any) function, you need to get nativeElement and then call the play() function because you are accessing DOM element directly:
#ViewChild('videoPlayer') videoplayer: ElementRef;
toggleVideo(event: any) {
this.videoplayer.nativeElement.play();
}
Credits to #peeskillet for this one.
Others have already answered the basic question (you must use nativeElement). However, since nativeElement is of type any you should 'cast' it to a more specific element type (for the <video> tag this is HTMLVideoElement).
const video: HTMLVideoElement = this.videoElement.nativeElement;
video.play();
This then gives you intellisense for all the supported methods and properties.
And of course this is all just compile time - you're not converting anything and you'll still get an error if the element is not really a video.
Here's another way to set your videoPlayer variable to use HTMLVideoElement for type safety
videoPlayer: HTMLVideoElement;
#ViewChild('videoPlayer')
set mainVideoEl(el: ElementRef) {
this.videoPlayer = el.nativeElement;
}
toggleVideo(event: any) {
this.videoplayer.play();
}
This is my HTML code:
<video controls class="video" (play)="video()" autoplay #videoPlayer>
<source src="assets/video/movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
This is my TS code:
#ViewChild('videoPlayer') videoplayer: ElementRef;
video() {
console.log('im Play!');
this.videoplayer?.nativeElement.play();
}
That's how I did it:
<video (click)="playVideo($event)">
<source src="video.mp4" type="video/mp4">
</video>
TS
playVideo(event) {
event.toElement.play()
}
I have problems to get a video to play on my Android mobile in the latest version of Chrome. In other browsers like the Puffin browser the video is playing. For test purposes I tried all common formats:
mp4
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/mp4" /></video>
<br />
webm
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE.webm" type="video/webm" /></video>
<br />
ogg
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE.ogv" type="video/ogg" /></video>
https://codepen.io/anon/pen/ozpVNP
According to Mozilla the first video, that is H.264 + AAC in MP4 should play. I also take this article in account and tried to play the videos by JavaScript additionally as well as tried to remove the type attribute on the first video tag without success.
How can I get it work in Chrome on Mobile?
<video autoplay loop autobuffer muted playsinline>
<source src="video/video-hat.mp4" type="video/mp4">
</video>
The problem is that Google want that users initiate by themselves any media, so If you debug your device chrome browser, you will get the warning "Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture."
So that means you need to attach the video initialization, for example, with a click event
There doesn't appear to be any great info on this, so thought I'd post my findings.
I've been debugging html5 video playback on Chrome desktop and mobile on an Android 5.0.1 Samsung S4 with Chrome 61 and the embedded browser, and Safari 9 & 11, using an automatic javascript play/pause written in AngularJS (below). The video is embedded in a carousel so is sometimes visible, sometimes not. In summary:
I would recommend having both webm(vp8/vorbis) and mp4(h264/aac) formats. These are the most supported formats and have equivalent quality for the same bitrate. ffmpeg can encode both.
It seems Chrome mobile prefers webm if it can get it, so put that first.
If a browser plays a file when you direct it to the file url, this does not mean it will play it when embedded in a video tag, though it will tell you if the format & codecs are supported if it does play. Chrome mobile seems very picky about having a video source whose resolution is too high.
Safari (and probably iOS) will not play a video unless served by a server supporting byte-ranges. Apache, nginx and Amazon S3 for example do support them, but many smaller web servers (like WSGI servers) do not.
The order of the videos matters more than the source media attribute. Always have low resolution versions of a video first. The example below uses 1920x1080 and 1280x720. It seems if the mobile browser encounters a video that is "too high-res", it just stops processing the other sources and prefers the poster.
having a controls attribute and manual play vs playing through javascript doesn't appear to make any difference.
the muted attribute stops android from putting a little speaker icon in the status bar when playing but off-screen, even when the video doesn't have audio. As a side-note, I'd also really think about your audience if you intend to autoplay video with sound. Personally I think it's a bad idea.
the preload attribute doesn't seem to make much difference. The browser will tend to automatically preload the selected video metadata anyway.
having a source type attribute does not stop the video from playing. If anything it helps the browser choose which source to pick for the best
the JS video.oncanplay event is the best way to see if the video tag has been successful. If you don't get that, the video won't play, but the browser won't tell you why.
HTML:
<video class="img-responsive-upscale ng-scope"
video-auto-ctrl loop muted preload poster="0022.png">
<source src="vid_small.webm" media="(max-width: 1280px)" type="video/webm">
<source src="vid_small.mp4" media="(max-width: 1280px)" type="video/mp4">
<source src="vid.webm" media="(max-width: 1920px)" type="video/webm">
<source src="vid.mp4" type="video/mp4">
<img src="0022.png" alt="something"
title="Your browser does not support the <video> tag">
</video>
Javascript:
<script type="text/javascript">
angular.module('myproducts.videoplay', []).directive('videoAutoCtrl',
function() {
return {
require: '^uibCarousel',
link: function(scope, element, attrs) {
var video = element[0];
var canplay = false;
var rs = ["HAVE_NOTHING", "HAVE_METADATA", "HAVE_CURRENT_DATA", "HAVE_FUTURE_DATA", "HAVE_ENOUGH_DATA"];
var ns = ["NETWORK_EMPTY", "NETWORK_IDLE", "NETWORK_LOADING", "NETWORK_NO_SOURCE"];
function vinfo() {
console.log("currentSrc = " + video.currentSrc);
console.log("readyState = " + rs[video.readyState]);
console.log("networkState = " + ns[video.networkState]);
bufinfo();
}
function bufinfo() {
// tr is a TimeRanges object
tr = video.buffered
if (tr.length > 0) {
var ranges = ""
for (i = 0; i < tr.length; i++) {
s = tr.start(i);
e = tr.end(i);
ranges += s + '-' + e;
if (i + 1 < tr.length) {
ranges += ', '
}
}
console.log("buffered time ranges: " + ranges);
}
}
video.onerror = function () {
console.log(video.error);
}
video.oncanplay = function () {
canplay = true;
if (!playing) {
console.log("canplay!");
vinfo();
}
}
var playing = false;
function playfulfilled(v) {
console.log("visible so playing " + video.currentSrc.split('/').pop());
playing = true;
}
function playrejected(v) {
console.log("play failed", v);
}
function setstate(visible) {
if (canplay) {
if (visible) {
p = video.play();
if (p !== undefined) {
p.then(playfulfilled, playrejected);
}
} else if (playing) {
video.pause();
console.log("invisible so paused");
playing = false;
}
} else {
console.log("!canplay, visible:", visible);
vinfo();
}
}
// Because $watch calls $parse on the 1st arg, the property doesn't need to exist on first load
scope.$parent.$watch('active', setstate);
}
};
});
</script>
I had an issue where the video worked on my desktop chrome, and desktop-mobile view, but not my iphone. Turns out i needed to add the "playsinline" property to the video tag. :]
The issue fixed for me after switching off "Data saving" mode in chrome.
I spend all my afternoon to fix an autoplay problem on iOS and discovered you just to disable the "ECO MODE" or it won't play automatically.