Reputation: 10828
Everyone who tried to make Youtube/Vimeo videos start play automatically on iOS knows that it could be a painful task. Apple blocked the 'autoplay' parameter for the right reasons, but sometimes you still need to get this functionality working.
I had the same issue with auto playing youtube videos, apparently, to get the autoplay to work, you need to do some javascript magic, listen for the player's 'onReady' event, than when the player is loaded and ready to play you call 'player.play()' to start it without any another user intervention.
Vimeo also got some javascript API, and I'm pretty sure you can do the autoplay trick with it, I just can't figure it up how to use it.
They have JS mini-library called Froogaloop
to make things easier, I saw this answer by @ila who use it in conjunction with the following html string:
NSString *htmlString = [NSString stringWithFormat:
@"<html><head>"
"<script src=\"froogaloop.js\"></script>"
" <script>"
"function ready()"
"{$f(document.getElementById(\"player\")).api(\"play\");}"
"function func1() "
"{$f(document.getElementById(\"player\")).addEvent(\"ready\", ready);}"
"window.onload=func1;"
"</script></head><body>"
"<iframe id=\"player\" src=\"http://player.vimeo.com/video/39287488?api=1&player_id=player\" width=\"315\" height=\"455\" frameborder=\"0\" webkit-playsinline>"
" </iframe></body></html>"];
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSLog(@"webview loaded");
NSString *path = [[NSBundle mainBundle] pathForResource:@"froogaloop" ofType:@"js"];
NSString *jsCode = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[webView stringByEvaluatingJavaScriptFromString:jsCode];
}
But this doesn't work for me, after adding alerts to this code, I can see that func1()
get called and executing the 'addEvent' line, BUT it seams that the ready()
method never gets called because the 'ready' event never fired (?)...
Any ideas?
Upvotes: 7
Views: 5080
Reputation: 12460
Loading a file locally or via a HTML string won't work due to the Same Origin Policy enforced by the web browser.
The iframe
is unable to propagate it's postEvent()
calls back to the main window because the Vimeo iframe
is being accessed via the http://
protocol and the local file is via the file://
protocol. The 'ready' event is sent via this mechanism.
It's possible to use the Vimeo API in this instance but in order to automatically play the video you need to know when the iframe has loaded but the "ready" event is sent from the iframe up to the window via postEvent.
The fact that it's using postEvent is is made clear by the code provided in the Vimeo API Documentation. Froogaloop also uses the same code
window.addEventListener('message', onMessageReceived, false);
If you run the most basic example of the Vimeo API in an HTML file on your machine Google Chrome will throw a descriptive message: (Safari does not show this)
Unsafe JavaScript attempt to access frame with URL file:///...index.html from frame with URL
http://player.vimeo.com...
The frame requesting access has a protocol of 'http', the frame being accessed has a protocol of 'file'. Protocols must match.
The code in question is simply: (See this gist for the full source)
<iframe id="player" width="" height="" src="http://player.vimeo.com/video/62207569?api=1&player_id=player" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
<script src="http://a.vimeocdn.com/js/froogaloop2.min.js"></script>
<script>
var player = $f(document.getElementById('player'));
player.addEvent('ready', function() {
player.api('play');
});
</script>
The proper solution is to host the HTML page on a remote service that has the same protocol as the Vimeo iframe. In this case anything from a http://
address.
If you load the above from http://(insert your host here)
it works instantly in the iOS simulator, Safari and Google chrome.
If you wanted to do more on device, you'd have to merge the two answers I've given; Poll the iframe until you deem it ready, then tell the player object to play.
Upvotes: 2
Reputation: 12460
My first answer to the question is a less than ideal brute force method. I'd suggest looking at my second method using the Vimeo Javascript API and froogaloop.
I'm going to assume you're using the Vimeo iframe inside a html page and that you're using this page inside a UIWebView inside an iOS app or inside Safari.
A little bit on introspection into the Vimeo iframe shows that it doesn't load the html video tag initially. You're going to have to programatically tap the 'play' button for it to load the video.
In order to do that today (April 2013, it may change) you can just grab the right elements and call the right functions. It's best demonstrated with some working sample code.
// You are loading this page inside a UIWebView
<html>
<head></head>
<body>
<iframe width="" height="" src="http://player.vimeo.com/video/62207569 " frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
<script>
// Add a listener for the window's load event
window.addEventListener('load', onWindowLoad, false);
function onWindowLoad(event) {
//use a loop to continue checking the vimeo iframe for the 'play' button
checkForTrue(isIframeButtonLoaded, iFrameButtonLoaded);
}
function checkForTrue(func, callback) {
setTimeout(function() {
if (func()) {
callback( iFrameButton() );
} else {
checkForTrue(func, callback);
};
}, 1000);
}
//finds the 'play' button within the Vimeo iframe
function iFrameButton() {
//window.frames[0].document.getElementsByTagName('div')[1]; // this also works...
return window.frames[0].document.getElementsByTagName('button')[5];
}
//simple boolean condition to check for the iframe button
function isIframeButtonLoaded() {
return ( iFrameButton() != null );
}
//once the button is loaded, click it
function iFrameButtonLoaded(iFrameButton) {
iFrameButton.click();
}
</script>
</body>
</html>
This source code is also available as a gist
A sane person may say this is not the best way to do it, but for the purpose of automatically playing a vimeo video within your iOS app it does seem to work.
The code to load the html file from your bundle and load it into a UIWebView is boilerplate:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:@"VimeoTrial" ofType:@"html"];
NSString *htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[self.webView loadHTMLString:htmlString baseURL:nil];
}
Upvotes: 8