I recently became the owner of an Android phone* and found that, despite it being listed as a feature of the browser, the HTML5 video element didn’t work for almost all of the examples I tried. I’ve just done some experimentation with this and think I’ve found a solution, so this post is offered in the hope that it helps anyone who may be tearing their hair out over the same problem.
From what I can tell, there are three requirements for video to work in Android browsers:
- You must not use the
typeattribute when calling the video - You must manually call the
play()method using JavaScript The video must be encoded as .m4v, not .mp4Update: This is not correct (see below)
Update: This may be a specific encoding issue rather than all .mp4s; some .mp4 videos seem to play with no problems, others do not. Further update: The video type was a red herring; see my follow-up post, Encoding Video for Android, for more about this.
You can see this working in the demo attached to an older post of mine: Demo: HTML5 Video Controls With JavaScript. This works,
<video id="video" autobuffer height="240" width="360"> <source src="BigBuck.m4v"> <source src="BigBuck.webm" type="video/webm"> <source src="BigBuck.theora.ogv" type="video/ogg"> </video>
The first source element calls the video in .m4v format, without specifying the MIME type in the type attribute; I’ve tried both video/mp4 and video/x-m4v, and neither works. Omitting the type attribute altogether lets the video play, and seems to have no ill-effect on other browsers which play the .m4v file.
In order to play the video in Android, I also have an event listener in the JavaScript which plays the video when the element is clicked on, somewhat like this:
var video = document.getElementById('video');
video.addEventListener('click',function(){
video.play();
},false);
I tested this on my own phone and an HTC Desire, and it works just fine on both. Hope this is of help to someone.
* It’s a Samsung Galaxy S, and I’m delighted by it.
It’s hard to believe that HTML5 video is still so badly broken in Android, even in the latest version. This should have been working since version 1 and they have no excuses — the markup has been out there and in use by the iPhone for *THREE YEARS*. I’m irate at Google for their incompetence with HTML5 video on Android. Where does one file a bug?
Hi Kroc, I’ve added this blog post to an open bug, number 8272 — I encourage you to do the same.
@KROC_CAMEN — HTML5 video support isn’t perfect, but the example doesn’t work on iPhone. Maybe you should check next time before going on a rant and spouting bullshit.
Wait; my example doesn’t work on iPhone? It certainly did when I checked it. Are you using iOS3? There’s a well-known bug with that, where the
posterattribute causes problems.Also, please try to be civil.
are there any special settings to encode the video with? The Javascript works fine, but as soon as I click the icon I get a message telling me “Video can not be displayed. This video is not a valid streaming media format”. Any ideas what might be wrong with the video (it’s a .m4v Format). Thanks!
Hi Kirsten,
Thanks for the comment. Your result is interesting, because I don’t get that message at all; I get the same message on some .mp4 files. What phone and version of Android are you using? I’m going to look into this further.
Peter
Hi Peter,
thanks for the quick reply. I am using the HTC Desire with the current standard version Android 2.1 update1. I tried various encoding settings. There was no chance with the mp4 encoding, as you have written. I use ISkySoft as converting software and the encoding settings were: M4V –MPEG — 4Video(*.m4v), Codec: H.264
Any idea? The alternative .ogv File is available as download only.
Thanks in advance! Kirsten
Kirsten,
I’m going to put together a test page, and we’ll see if we can get to the bottom of this.
Peter
Kirsten, could you take a look at this test page:
http://broken-links.com/tests/video/comparison.html
And let me know which of the videos (A,B,C,D) works for you? I’ve got a fairly good idea of what the problem is now, but want confirmation.
Peter
Hi Peter, Video A and B worked perfeictly. With C and D I got the same error message as with my movie. I am looking forwarnd to your answer. Kirsten
Hi all,
This is a good article.
Thank you very much.
But i have an issue (not small).
We can watch video on Android but it can be autobuffer (or preload).
On iPhone, you can press PAUSE and wait the player buffer the video. Then you can watch whole video without delay.
On Android, even you press PAUSE, but it just buffer 1/20 of video and stop buffer.
THen you watch video, if your internet is slow, the video will be delay to load… many times.
Please help me to solve this problem.
I am trying to find the solution for this whole week, but i still can not find out…
Please…
Thank you very much.
Regards,
Cuonga
@Kirsten: OK, so all four test videos were encoded using http://handbrake.fr; the only difference is that A & B used the ‘web optimized’ setting, C & D didn’t. I don’t know exactly what that does (rearranges the MP4 files so they stream better, from what I can tell) or how to make this happen in other encoding applications, but in the short term this will help you encode video. In the longer term, I’m going to look into this some more.
@MiniHD.mobi: I don’t get that problem on my Samsung Galaxy; may be a phone issue rather than an Android issue? What version of Android are you on? (Also I prefer if you use a name or nickname rather than a company name; it makes it harder to tell spam from genuine comments if you use your company name as your user name).
Hi Peter
Thanks for the great info. Can I ask you a question please.
I’ve made a simple html5 video page. Please see the code below
#script#
var video = document.getElementById(‘video’);
video.addEventListener(‘click’,function(){
document.play();
},false);
#/script#
#video width=“320” height=“240” poster=“poster.png” autobuffer controls#
#source src=“TV_intro.m4v”#
#source src=“TV_intro.mp4” type=“video/mp4”#
#source src=“TV_intro.ogv” type=“video/ogg” /#
Download the #a href=video.ogg#video#/a#
#/video#
But it doesn’t work on my htc desire though.. Can you kindly have a look at my code if I’ve done anything wrong? It works on iPhone.
Thanks in advance
ps. I just changed the mp4 extension to m4v to make m4v file as I read it works this way. No?
Jun
@Jun: As mentioned, it also depends on the way the video is encoded; see my comment to Kirsten, above.
Hi Peter
Thanks for the rapid reply. So do you think that the html itself is fine?
Thanks
Jun
Yes, the HTML seems fine; you just need to encode the video correctly. Try using Handbrake, and set the ‘web optimized’ option.
hmmmm.…Yes I used Bandbrake with ‘web optimized’ checked. but no luck yet.. maybe need more googling.. haha
it must be simple just don’t know what it is.
Thanks
Hi Peter
The reason was javascript. Once changed js it works. but only sound. screen is just black. one solved but another came out. Any idea? Anyway will post if there’re any outcomes for other people who have the same issue.
Hi Peter,
I changed the encoding as you said and now it does work perfectly. Thank you very much for your quick replies!
does not work on htc magic w. A V:1.6
The JS code fixed my Android issues but it has “broken” the pause/play button on all other browsers once the video has started to play. I imagine this is due to conflicts between the EventListener and the ‘click’ function of the play button i.e. you’re essentially hitting play twice and this causes the video to immediately pause after the play. The example on http://diveintohtml5.org/video.html also exhibits this problem — just try and Play -> Pause -> Replay and you’ll see what I mean. My workaround at the moment is to sniff for UserAgent and only add the EventListener if it’s an “android” — but has anyone got a better solution?
var uagent = navigator.userAgent.toLowerCase();if (uagent.search(“android”) > –1) {
var video = document.getElementById(‘video’);
video.addEventListener(‘click’,function(){
video.play();
},false);
}
@Jun I’m getting the same thing as you. It “plays” the video, but it only has audio with a black screen. I just have a link straight to the mp4 file with no javascript.
I’m trying to figure out how to output once from Camtasia Studio (with web format) to mp4 and have it play on all browsers, iPhone/Touch/Pad, and Android. It’s all working right now except for this problem with Android :S
I know this is way late, but it’s worth mentioning that you can keep the type=“video/mp4” on the first source, and then move it to the video element’s .src attribute for Android. Something like:
var video = document.getElementById(‘video’);
video.src = video.childNodes[0].src;
video.addEventListener(‘click’,function(){
video.play();
},false);
I know this is arcane, but it may be the real reason for most problems playing video on Android:
***Make sure the “moov” atom comes before the “mdat” atom in the file.***
In Handbrake, for instance, you would check “web optimized” then make sure that “2 pass encoding” is enabled — this second pass is required to re-order the elements in the file such that Android will recognize it, since the natural order these elements are calculated in during single-pass encoding is the reverse.
@Matt: I won’t pretend to know what that means, but that does sound right; I read something similar to that on a forum somewhere.
Hi Peter,
Are these code applied for Android’s browser only not for Android native application?
I just created an Android application that run .m4v video file using your code. I used PhoneGap framework for this application so I can use html and Javascript to create an app. But the code didn’t work well. It couldn’t run the media file.
Could you pls give me any advices?
Thanks,
Thom
@Thom Sorry for the slow reply. I don’t know anything about Android app development, and haven’t used PhoneGap, so I can’t give you any advice on this. Sorry.
Hi Peter, am a newbie to android… am trying to run a video in html5(). i’ve read all the comments posted and came to know abt the procedure to run vids on phones. But i want to run thm on emulator. Cld u pls hlp me out of this of avd 2.2 or 2.3.
Thank you.
@Vinay I’ve never been able to get video working on the emulator, and a lot of people seem to have the same problem. Most of the time I just get the audio. Try searching the Android developers forums and see if you can get a decent response from there.
Peter,
I don’t know if this is helpful info or not, but I’ve just checked and all of those videos (A-F) on the video comparison page work on Android 2.3 (Nexus S)
Thanks
@Tom — Very useful, thanks.
[…] Displaying HTML5 Video for Android Tutorial at Broken Links […]
[…] Making HTML5 Video work on Android phones Related: iPad is the new IE6 […]
Worked fine with HTC Desire[Android 2.1] and iPhone4[iOS 4.2.1]
Hey Peter … This may be late to the game but I read today on Video for Everyone that Android has to be tested using real phones when it comes to video; the emulator won’t play them. Reference: http://camendesign.com/code/video_for_everybody/test.html
Blurb: “HTML5 video on Android is badly broken. Resolution support varies from one handset to the next (often just 480x360), the fallback image usually doesn’t show and the code requires special adjustments. The Android emulator is completely useless as it doesn’t represent any real hardware and does not play HTML5 video. THERE IS NO WAY TO TEST ON ANDROID WITHOUT A PHYSICAL PHONE. BLAME GOOGLE.”
Thanks Rynne. My experience is that the screen will go black and play audio, but there’s no video playback. While that’s not great, it does mean that there’s enough feedback for you to tell if a video would play or not. But yes, testing on a physical device is better; the Android emulators are *slow*.
I am trying to get a movie (mp4) to work on both ios and android. I am writing on a mac and using mainly BBEDIT or Dashcode, and editing the *.js file.
I was wondering if you know what I can write to enable android to work?
the js file is:
function writeMovie1()
{detectBrowser();if(windowsInternetExplorer)
{document.write(”);}
else if(isiPhone)
{document.write(”);}
else
{document.write(”);}}
setTransparentGifURL(‘Media/transparent.gif’);function hostedOnDM()
{return false;}
function onPageLoad()
{loadMozillaCSS(‘Gallery_files/GalleryMoz.css’)
Widget.onload();fixupAllIEPNGBGs();fixAllIEPNGs(‘Media/transparent.gif’);fixupIECSS3Opacity(‘id2’);performPostEffectsFixups()}
function onPageUnload()
{Widget.onunload();}
So what’s the deal with Android 2.2 then? None of these solutions seem to work for that one, and I’ve tried them all — the js play call trick, removing the codecs, removing the type attributes, all of the above.… I even went to your Demo here: http://broken-links.com/tests/video/ with the 2.2 droid and sure enough, it would not play the video. Gave me a spinner for “forever” and then on refresh popped up that “video cannot be played” message.
Really? I have Android 2.2 and it works fine for me. When you have a chance, take a look at this page and see if any work for you:
http://broken-links.com/tests/video/comparison.html
I tested these on an Android 2.1 device and all played except “C” and “F”. I haven’t had a chance to use again the Android 2.2 phone I was using previously, though. At this point I’m pretty convinced the problem is with how the video is encoded, so I’m gathering info in that regard to see if we can’t get to the bottom of this (including your Encoding article — thank you! Did you ever resolve the iProducts issues on some of those examples, by the way?)
worked on my optimus v except c and f running android 2.2
I’m having the same problem as Stupidian mentioned before. If I apply the play or pause control to the video tag itself, I lose the play or pause control from the default controls. (Actually, it acts like I’ve double-clicked the control. When I click on play on the controls, it advances one frame then stops. If I click on the video, play continues.)
I noticed that the video works in http://diveintohtml5.org/video.html now, but from Chrome (for example), there is no control by clicking on the video itself. Any idea of how they are getting around this (like a sniffer, because they aren’t claiming to use one), or how do I get around this in general, preferably without sniffing?
Is there a DOM access to the default play controls? I’d like to have the option of playing by clicking on the play control or by having a giant play button overlay on the poster, because most video players use the standard of clicking either one.
does both android and iphone only play embedded video via it’s native player only? I want it to play on the page…not a popup.… is it possible?
[…] Javascriptでトリガーを設置してあげないとフルスクリーン再生してくれなかったりするようです。 […]
[…] Addressing challenges playing audio and video in the Android browser. […]
less lines with this.play();
[…] read this post Making html5 video work on android phones. But I believe I’ve got that covered in my code above. Anyone see what I can do to get this […]
Hello everybody. First thnx a lot for this code for video for android it works perfectly. Now I wanted to combine with a code for redirecting to another url and it doesn’t work on android. While it’s working in mozzila and safari. Any help? you can see my page
here
and here is code I used:
var video = document.getElementById(‘myvideo’);
video.addEventListener(‘click’,function(){
video.play();
},false);
var video = document.getElementById(“video”);
video.addEventListener(“ended”,doSomething,true);
function doSomething() {
window.location = “http://www.reyescaballerorey.com/voodoo_page/news.html“
}
This really saved the day for me in terms of raw functionality to play the video. I was frustrated that I could get the video to play on all HTML5 devices and browsers (including other android phones) except my Ginger-bread based Rezound. It was not an encoding issue, just a click-to-play issue. The video would play if I tapped in the lower left corner of the video area, so it seems as if for some reason the browser or the device makes the controls for video invisible. Instead of making the entire video area hot (clickable), is there a solution to make those video controls visible for browsers/devices that might be hiding them?
Rather than adding an event listener, I simply take advantage of the play() method:
<video onclick=“this.play();” preload=“auto” controls=“controls”>
<source src=“movie.mp4” />
</video>
I own a Samsung Galaxy S2 and i dont have a problem about videos. Maybe its about the version of the android ????
@FredMC Using inline JavaScript is bad practice, which is why I’ve used an event listener.
I am developing android app using phone gap in which I am using HTML5.Can you please tell me in which folder I should keep my video to make it work..
Thanks a lot.
Thank you for all the info which i had pulled my hair over.
I am running php site displaying html-5 video and embed others
like youtube.
I tried above javascripts but does not work well. Especially my version of android stock safari browser running on Samsung G. S2
does not detect anything on the UA while if i switched to Chrome on the same device it does (strange!).
So i come out with a modified method that work well for me.
Tested on: Windows XP chrome, Samsung Galaxy S2, iPad2.
1. Let the php script which displays my html-5 videos detect browser UA.
a. get this simple php class to detect ua type (or any one available).
http://code.google.com/p/php-mobile-detect/wiki/Mobile_Detect
b. Give different video tag treatments if found to be android IOS and safari. (note chrome on android is working perfectly, so above methods memtioned by a few, which test only for android will fail chrome on android, that’s why i use this approach together with onclick=‘this.play(); suggested by FREDMC above, Thanks).
Codes:
if ( $detect_mobile->isSafari() AND $detect_mobile->isAndroidOS() )
{
echo “”; }
else
{
echo “”;
}
and follows by the usual video stuff.
This works perfectly for me on different devices and PC using different browsers.
hope it helps.
Soemthing was missing in my post above.
if detech to be safari and androd, i will insert this to video tag:
onclick=‘this.play()’
[…] If you experience problems with MP4 video playing on earlier version of Android you may wish to explore removing the type attribute for the MP4 source – as suggested in Peter Gasston’s post. […]
Your demo runs on Ipad 2, I’d to run a single mp4 video file and perfoms OK when I touch the Ipad screen
install vplayer version 3.1.3
Click on Video download Link, Android system,open with VPlayer
it will stream it :)
The movies works great on originale browser on phone. My question is, how can I modified a webview, so it play that movies.
An additional consideration is that MP4 video that resides on a server requiring authentication or in a password protected folder will not work in Android Chrome (4.2). It will however work using Firefox for android (diff format as WebM but also not locked down as the MP4 evidently is).
You can however have an HTML page containing the video tag reside in a secure location as long as the folder where the video is doesn’t require authentication.
It’s a messed up issue that I hope is resolved in later versions of Android Chrome …
For the life of me I cannot get this to play on my android 4.0.4 tablet.
I downloaded the video, put the code on my page and tried playing it in a a phonegap webview, it just wont happen! Any ideas? Can you make this play inside the webview?
Im trying to start the video with a simple video.play() once the page has loaded but this does not work. Any idea why? I mean whats the diference? It works in my dektop browser. Can you not do .play() without an event listener?
As Stupidian already pointed this out a few years ago: the example code somewhat breaks the HTML5 player of devices other than the one targeted by the fix. So to do it correctly, you’ve to check the User-Agent and apply the fix only for Android versions 2.0.* — 2.2.*. The problem got fixed in Android 2.3.
A better example code could be like this:
function myOnload() {
var ua = navigator.userAgent;
if (typeof ua != “undefined” && ua.match(/Android.* 2\.[0 – 2](\.[0 – 9]+)*[^.0 – 9]/i) !== null) {
var vid = document.getElementById(“video”);
vid.addEventListener(“click”, function() {
vid.play();
}, false);
}
}
window.onload = myOnload;
Another issue many complained about is that (for them) the example doesn’t work at all on 2.2.* Android versions, the playback doesn’t start when you click the video. I had this issue on phones where JavaScript was disabled. Obviously your code won’t run in this case. To cover for this, you can add some warning about the necessity of JavaScript for playback in a NOSCRIPT tag below the JavaScript code.