I'm trying to play an HTML5 video in reverse on an iPad (The video needs to switch between forward and reverse arbitrarily based on user input).
The HTML5 <video> element includes a property called playbackRate which allows video to be played at a faster or slower rate, or in reverse. According to Apple's documentation, this property is not supported on iOS.
Playing in reverse can be faked without the use of playbackRate by setting the currentTime property multiple times per second (e.g. 10-30 updates per second). This approach works on desktop Safari but it seems that seeking is capped on iOS devices to around 1 update per second - too slow in my case.
Is there any way to play an HTML5 video backward on an iOS device (namely an iPad)?
(I'm testing on an iPad 2 running 4.3.1)
As Mihai suggested, use the two versions and update the seek location when the user changes the playback direction.
Layer the videos in DIVs on top of one another, and when the playback direction is flipped, toggle the div visibility (and pause playback of the the one being hidden).
So this is the timeline:
User clicks playback toggle.
Pause displayed video.
Get Seek location of displayed video.
Subtract that value from the video duration.
Seek to this value in the non-displayed video.
Toggle displayed video DIVs.
Begin playback of newly displayed video.
The playbackRate attribute is now supported on iOS 6 Safari.
Why not stitch the reverse and forward versions together into one movie?
That removes the problem of unloading and loading video when the user flips the direction. With a single movie approach, when the user flips direction, all you need to do is figure out the corresponding point in the other half of the movie and seek to there.
My suggestion is to make a "fake" video player in your HTML code. Then capture the user's attempt to "play" the video using the safari/ios callback methods. Then create a MPMoviePlayerController that actually loads the video and display it over the original position of the video in the browser or only support full screen play. MPMediaPlayback protocol supports reverse playback via the currentPlaybackRate property so hopefully, this should be a temporary fix as I can't see the iOS version of Safari not eventually implementing this feature since it is supported by the native player.
NOTE: I was stupid and missed a non-trivial part of the question, so the following is pretty useless for iOS purposes
After a moment of Googling, I found the following code along with explanation on how to support reverse-playback of html5 video on Webkit based browsers:
function speedup(video, direction) {
if (direction == undefined) direction = 1; // or -1 for reverse
if (video.playbackRate != undefined) {
video.playbackRate = direction == 1 ? 2 : -2;
} else { // do it manually
video.setAttribute('data-playbackRate', setInterval ((function playbackRate () {
video.currentTime += direction;
return playbackRate; // allows us to run the function once and setInterval
})(), 500));
}
}
function playnormal(video) {
if (video.playbackRate != undefined) {
video.playbackRate = 1;
} else { // do it manually clearInterval(video.getAttribute('data-playbackRate’)); }
}
Source: http://net.tutsplus.com/tutorials/html-css-techniques/html5-audio-and-video-what-you-must-know/
You need to pass in the html5 video object to the speedup function, but then again that function could possibly be reduced into the following (I haven't tested this yet, it is an iPad specific function):
function reverseVideo(video) {
video.playbackRate = -1;
}
Feel free to play around, and search for more information on the html5 video element :)
Related
Is it possible to do Airplay audio streaming like Spotify or Amazon Music. When i setup an Airplay stream with Audio from my App the screen (on the Apple-TV) turns black and shows only the progressbar.
Is it possible to show the small hint in the top corner with all the audio information which disappears after a few Seconds and don't block the whole Apple TV Ui?
Or is this kind of a Spotify / Amazon Music privilege?
We had this problem as well. I believe that there are some bugs here in Apple's court, but we found a decent workaround that seems to be pretty safe from side effects.
We found that setting the player's allowsExternalPlayback field to NO would sometimes correctly stream the audio without the blank video screen (along with correct display of the now playing information, correct response to volume rocker etc...). However, we found that very often it would fail to play anything at all.
Doing some runtime introspection, we found that the player would always correctly buffer from the network. But when it would hit the isPlaybackLikelyToKeepUp event, it would set the player's rate field to 1 indicating that it is playing, but more often than not, not actually play the audio. No errors were reported and so from all we could tell, the player itself thinks that it is indeed playing when it is not. We found this hangup to only occur when we had set an AirPlay device for audio output.
So we found that in certain event callbacks and other key places, if we added a simple one-liner:
if( self.avPlayer.rate == 1 ){ self.avPlayer.rate = 1; }
It would kick whatever internal hold ups were causing the player to not actually AirPlay and correctly stream the audio. If the player was already correctly playing, then no harm done.
Is there a way to detect if audio can't be muted? In iOS devices, audio cannot be changed through javascript. I have a button in my app that mutes audio played using SoundManager2 and HTML5 video. This doesn't work in iOS devices. I could check for iOS and handle accordingly, but I am not sure if any other devices are handled this way and its better practice to do more feature detection than device specific changes. I tried checking for the muted parameter and it does change, just doesn't reflect, so I can't do something like this:
soundManager.mute();
if (!soundManager.muted) {
alert("Can't Mute");
}
The mute function also just returns null, so its not like I can look at the returned value of that either.
Is there something I am missing or do I need to check for iOS specifically?
I use feature detection.
First I save the current volume, then I set it to 50%, and check if really is set to 50%
If yes, the device can change volume.
Finally I set the volume back to the original value.
var tmpvol = myAudio.volume;
myAudio.volume = 0.5
if (myAudio.volume == 0.5) {
// true
}
myAudio.volume = tmpvol;
The rel parameter in YouTube API dictates whether or not related videos are shown at the end. When rel=0 the video reverts back to the thumbnail with a play button.
However on mobile (tested on iPhone / iPad / Fire Tablet) when the video goes back to the thumbnail it cannot be played a second time. It just does nothing.
I reported the issue to Google but nothing yet after a few days.
I had to resort to destroying the video and recreating it but this makes for a kind of nasty flickering.
My experience with YouTube issues is they never seem to end up fixing anything related to iOS - so I was wondering if there was any other kind of trick to prevent this.
Test page
The trouble with refreshing a webpage at a specific interval is that you dont know exactly when the video ends so you need to develop a method which the video player sends a signal when the video ends, which would then start the script to refresh the page. Otherwise you end up restarting it in the middle of the video. so personally, I would not even mess with refreshing the page. For Audio players it works ok because audio is smaller and streams more quicker. Video dont.... they always stop to buffer.
So YouTube API uses "Events" and "Listeners", so in particular, you need to design around the Event: "onStateChange".
When onStateChange = "ended" (zero) the video has ended, so then you reload the video player with the same video and set it to its Ready State again.
In theory its very easy you basically need to setup and control the entire video player through javascript. And the API gives examples on that.
http://code.google.com/apis/youtube/js_api_reference.html
http://grizzlyweb.com/webmaster/javascripts/refresh.asp
http://code.google.com/apis/youtube/forum/
Have a look at loop and playlist parameters as well. You can set playlist parameter to video ID and same video can be replayed using this.
So, it will be something like:
http://www.youtube.com/embed/{VIDEO_ID}?wmode=opaque&loop=1&version=3&playlist={VIDEO_ID}
Hope this helps!
Appears to have been fixed by YouTube.
I can now play the video multiple times (on multiple devices) without it getting stuck. Was too busy wondering why my question was getting so little attention that I forgot to check again to see if it was fixed ;-)
My website is running Bootstrap 3.0 and I have an intro video and full length video hosted on YouTube that I am trying to implement. The intro video autoplays when the page is loaded, and then I have a button that opens up a modal window with the full video with audio.
I would like to stop the video completely on close of the modal window so that if they click the button to open it again, the video starts from the beginning. Unfortunately, the stopVideo function doesn't seem to be working how I would expect. Basically, it's just pausing the video, so if I open the modal back up, the video starts playing right from where it left off.
How can I make it so that the video stops and starts from the beginning if it's reopened?
Here is my current code:
$('#myModal').on('show.bs.modal', function () {
$('#placeholder')[0].contentWindow.postMessage('{"event":"command","func":"' + 'pauseVideo' + '","args":""}', '*');
$('#full')[0].contentWindow.postMessage('{"event":"command","func":"' + 'playVideo' + '","args":""}', '*');
});
$('#myModal').on('hidden.bs.modal', function () {
$('#full')[0].contentWindow.postMessage('{"event":"command","func":"' + 'stopVideo' + '","args":""}', '*');
$('#placeholder')[0].contentWindow.postMessage('{"event":"command","func":"' + 'playVideo' + '","args":""}', '*');
});
Thanks!
You can use seekTo to get back to the begining of the video when the modal is open.
An play the video after the seekTo
Doc from API
player.seekTo(seconds:Number, allowSeekAhead:Boolean):Void
Seeks to a specified time in the video. If the player is paused when
the function is called, it will remain paused. If the function is
called from another state (playing, video cued, etc.), the player will
play the video. The seconds parameter identifies the time to which the
player should advance.
The player will advance to the closest keyframe before that time
unless the player has already downloaded the portion of the video to
which the user is seeking. In that case, the player will advance to
the closest keyframe before or after the specified time as dictated by
the seek() method of the Flash player's NetStream object. (See Adobe's
documentation for more information.)
The allowSeekAhead parameter determines whether the player will make a
new request to the server if the seconds parameter specifies a time
outside of the currently buffered video data.
We recommend that you set this parameter to false while the user drags
the mouse along a video progress bar and then set it to true when the
user releases the mouse. This approach lets a user scroll to different
points of a video without requesting new video streams by scrolling
past unbuffered points in the video. When the user releases the mouse
button, the player advances to the desired point in the video and
requests a new video stream if necessary.
I also encountered this problem,spend hours digging into it. however I didn't find a sure reason, but the following reason may be it:
("stopVideo()") Stops and cancels loading of the current video.
and
Important: Unlike the pauseVideo function, which leaves the player in the paused (2) state, the stopVideo function could put the player into any not-playing state, including ended (0), paused (2), video cued (5) or unstarted (-1).
This is quoted from the YouTube API page
But I'm confused by this, because even if the background mechanism are not the same between stop and pause api, they act still identical(sometimes), so I'm still confused and curious about the real usage of stopVideo().
I am trying to play a video on iPad, my code is below :
public function init_RTMP():void
{
videoURL = "http://rest************_iphone_high.mp4";
vid = new Video();
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, onConnectionStatus);
nc.connect(null);
}
private function onConnectionStatus(e:NetStatusEvent):void
{
if (e.info.code == "NetConnection.Connect.Success")
{
trace("Creating NetStream");
netStreamObj = new NetStream(nc);
metaListener = new Object();
metaListener.onMetaData = received_Meta;
netStreamObj.client = metaListener;
netStreamObj.play(videoURL);
vid.attachNetStream(netStreamObj);
addChild(vid);
}
}
when i play it on my system it is working fine, but when i create a IOS app of it and installs on device, it shows white blank screen.
If anyone have same problem or any idea please share with me.
As VC.One pointed out, AIR for iOS does not play most (but not all, it will occasionally play a very specific encode type) h.264 encoded videos. There are three solutions:
As VC.One said, you encode as FLV. Doing this is not good and I would not recommend it. FLV is not hardware accelerated (unless things have changed recently and I have not seen the updates) and will run entirely off the CPU meaning your app will run slowly and the app will eat battery much quicker than normal.
Use StageWebView, in which case you just plug in the URL to the video and it will play the video using the native video player. This has the down side in that you cannot skint he player and you cannot control it. Once it begins playing, you have no control over it except for unloading the page. This works very well, however, and is fairly easy to implement, though the video will appear on top of the stage (it is not in the Display List).
The last option is to use StageVideo. This will play videos using the native framework, so you can easily play h.264 and it will be hardware accelerated. Additionally, this is just a NetStream player so you have full control over it. And best yet, it has no chrome so you can build a player around the video screen. However, like StageWebView, StageVideo is not in the Display List. But unlike StageWebView, it is rendered directly on the stage, below everything else. So the app itself will cover the video. You can get around this by creating a class to mask your app around the video, but it is incredibly difficult to properly pull off. It took me about 12 hours to create my StageVideo player and the masking class, plus another half day later on fixing issues with the masking class and how it handles DPI changes (hint: do NOT set applicationDPI if you are using Flex)
As always, make sure your AIR SDK is up to date as well. 3.5-3.7 have all added a ton of new features and bug fixes for iOS applications so updating to AIR 3.7 might actually solve or make your issue less of a problem (I don't think it will, but it is always worth a shot, right?)
See this link:
Netstream video not playing on iPad
Basically it was fixed by encoding the video file as FLV not MP4.