Autoplay audio on mobile safari - html

Before I get flamed to death, I know this doesn't work currently due to Apple's concern over downloading an audio file automatically.
However, my question is: Has anyone found a cunning workaround yet? I just want to play a start up sound on the launch of a game and currently have to wait for the user to click somewhere before I can play the audio. One of you clever chaps must have got this working by now?

There is no chance to get autoplay working in mobile browsers. Android and iOS doesn't allow it and personally I think that is a feasible confinement! Imagine every second website you will open plays and ugly sound at start!
But you can make a little hack, so that the user will not remark that he currently started the audio for your application:
You WILL need an user interaction to start your audio. So, your app or game maybe has a startscreen or a welcome button which needs a click to get to mainmenu or start the game. Bind to an user event (the accepted events are: "click", "touchend", "doubleclick" and "keydown") and call the load() method for your <audio>.
Bind to the "canplaythrough" event of the <audio>. This event is triggered when your source is ready to play. Here you can now call play(), pause() or wait for other interactions. So the audio is ready but now you have full controll when to start or stop the sound.
I also advise you to use audio sprites on mobile clients. iOS (and Android?) internally implemented audio support through a Singleton. That means that you cannot, like in desktop browser, have 10 audio elements and play differents sound at once. You can only play one file!
So changing the source for different sounds takes to much time. With an audio sprite you can start your sprites when the user first interact with your website or game. Pause your sprite and when you need to play sound you have to set the currentTime to the beginning of the sprite and pause the sprite when currentTime of your file reaches the end of your sprite. There is an timeupdate Event where your can check the currentTime of your sprite.
If you are more interested I can prepare my javascript audio sprites player for you!!

Only solution I have seen so far is to create a shell app and put the web app inside a UIWebView.
http://flowz.com/2011/03/apple-disabled-audiovideo-playback-in-html5/
UIWebView.allowsInlineMediaPlayback = YES;
UIWebView.mediaPlaybackRequiresUserAction = NO;
I also would really like to know how to do this in a plain-old web app.

I believe I just solved this for my own app.
The steps,
Controller loads up,
Then.... in viewDidLoad
have your web view load the HTML : loadHTMLString:htmlFile baseURL:[self getBasePath]];
THEN... set mediaPlaybackRequiresUserAction = NO on the webview.
If you set it too soon, I think the load for the html resets it.

I have a bot chat app that has voice messages and I needed them to be autoplayed whenever needed ... so here is what worked for me in my angular app :
just attach a click eventlistener to document and call player.load(), after that whenever you set player.src = x; it will autoplay.
<audio id="voicePlayer" controls autoplay playsinline #voicePlayer></audio>
#ViewChild('voicePlayer', { read: ViewContainerRef }) voicePlayerRef: ViewContainerRef;
...
ngAfterContentInit(): void {
this.voicePlayer = this.voicePlayerRef.element.nativeElement;
document.addEventListener('click', this._onDocumentClick.bind(this));
}
_onDocumentClick() {
this.voicePlayer.load();
document.removeEventListener('click', this._onDocumentClick);
}
...
this.voicePlayer.src = 'x';

HowlerJS creates is a workaround. The user doesn't need to allow autoplay for the audio to be played automatically
Explanation from Docs on how this workaround is created :
howler.js is an audio library for the modern web. It defaults to Web Audio API and falls back to HTML5 Audio. This makes working with audio in JavaScript easy and reliable across all platforms.

Related

HTML5 Video element does not a resume live streaming when a stream is interrupted then restarts

I'm using JW Player to live stream content onto a web page. The player is backed by an open-source library called cine.io.
My issue is that the player falls back to an HTML 5 video element for all mobile web, both on iPhone and Android. There are some differences between the flash solution of JW Player and HTML5 - notably that if a live stream starts, then stops, then restarts, the video element will not pick up the restarted stream.
This is a problem since streams often drop in and out - and the flash solution does pick up the restarted stream.
I tested a bunch of listener methods on the video and the only one that signalled that the stream had ended was a "time update" listener:
$video.on('timeupdate', function(){
//Do something
});
However none of my attempts to re-open the stream have been effective.
Is this even possible? Can anyone provide pointers?
Would an example like this work?
http://support.jwplayer.com/customer/portal/articles/1442607-example-a-custom-error-message

HTML5 web audio seekTo for buffered source

I have web application(similar to Karaoke) where user can record his voice over instrumental.
After recording user plays back recording. Here I play instrumental in <audio> tag and voice using web audio api. To sync both audios on play/pause I calculate time like this
pausedAt = Date.now() - startedAt;
startedAt = Date.now() - pausedAt;
This works fine. Issue is when user uses slider on audio tag to move forward/backward. I am thinking of solution like this
Use ontimeupdate event, stop the voice and then use startAt(currentTime) where currentTime is of instrumental playing in audio tag.
Since there is no seekTo function in api, I have to stop and then start audio. Is there any better solution for this?
Second issue I face is seeking on audio tag is not smooth. If I arbitrarily clicks on progress bar sometimes it doesn't work. When I saw network tab in developer tool window I saw something like shown in image. It sends out some 600 requests and some 86 MB data downloaded whereas file size is less than 10 MB.
You really should use the Web Audio API to do this. will never give you precise synchronization, and it will rely on streaming to seek - which is going to result in extra downloading, as you saw. Just load the song via XHR and decodeAudioData, and provide your own playback controls.

as3 - flvplayback component - disable auto buffer?

I'm using the flvplayback component in an AS3 movieclip. I do have the source defined in the compontents properties to a video hosted on Amazon s3.
Now the problem is as soon as the swf loads in a browser it starts downloading/buffering the video even though it's not set to autoplay.
Is it possible to only have it start downloading if the play button is clicked (I do have a custom play button hooked up to player via AS3)? I have 3 separate video players in the swf each with fairly large videos and I don't really want to burn through a ton of bandwidth especially if the user only plays one video.
Thanks!
I haven't used the flvplaybackcomponent, but I'm assuming as soon as you specify a url, it'll start downloading. Try either not setting that until it's been interacted with, or -- do what everyone else does -- place an clickable image on top, then once that's done, create your video player.

How to "autoplay" an HTML5 audio element in Mobile Safari?

I am porting a vehicle in-dash display unit app over to the browser. The big goal is to get it running completely within Mobile Safari.
It's an HTML5/JS music app that relies heavily on jQuery.load to move around between different "screens" by loading in page fragments.
The issue is that when a user selects a track to play, they are taken to the "now playing" screen, which should start playback of the track. The track is not playing though once this screen is reached, and the user instead needs to explicitly click play from this screen in order for audio playback to start. Once this has happened for the first time, autoplay works for the duration of the app.
I understand that Mobile Safari intentionally put blockers in place to prevent audio from autoplaying so that web apps are kept from consuming data unless in direct response to user input.
The thing is, my audio playback IS in direct response to user input...sort of. However, a bunch of things need to happen before my playback actually starts, and those things happen within the now playing page (calling API to get URL for track to be played, report user is playing track, get track metadata, yatta yatta yatta).
To try and get around this, I have the app preload a silent .1s mp3 file into the audio element on startup. Then in direct response to a click event to transition to now playing screen, I call .play() on the audio element.
I assumed that having a call to .play in direct response to user input would the subsequent call to .play() within the now playing page to work, since this is the behavior I had previously observed.
Only, it didn't seem to make any difference.
Any ideas on how I can adjust my flow in order for audio playback to start after loading the now playing screen?
EDIT:
Added some code snippets below
Vehicle.audio = {
init: function () {
audioElement.setAttribute("src", "/audioinit.mp3");
audioElement.play();
},
play: function (source) {
log("VEHICLE: playing audio from source " + source);
Vehicle.audio.stop();
audioElement.setAttribute("src", source);
audioElement.play();
},
In response to user selecting a track:
$(document).on("click", "a.play-track", function () {
Vehicle.audio.init();
/* my wrapper function for jQuery.load() */
replace_wrap("nowplaying.html");
});
Then on the now playing page, Vehicle.audio.play() is called.
The thing is, my audio playback IS in direct response to user input...sort of. However, a bunch of things need to happen before my playback actually starts, and those things happen within the now playing page (calling API to get URL for track to be played, report user is playing track, get track metadata, yatta yatta yatta).
Try adding a "touchstart" event listener to the entire "now playing page" which will then synchronously call .play() on the audio element:
$(document).one("touchstart", function () {
Vehicle.audio.init()
})
This way as soon as an iOS user touches anywhere on the now playing page, the audio should begin loading/playing.
AFAIK it is a restriction placed intentionally by iOS. User must interract with the device (touch/click event) before the script is allowed to start playback.

iOS HTML5 video player next/prev buttons

Is there a way to access/listen to the previous/next buttons in the iOS HTML5 video player? Ideally I would listen to some sort of a prev and next event and swap out the videos accordingly without the user having to close the video and click my prev/next buttons.
(source: iphonefaq.org)
I am currently using jwplayer to generate the html5 video and listening to their playlist next/prev listeners don't seem to do the trick. I can always find and attach listeners to the actual <video> tag pretty easily though.
If you attach listeners to the video tag itself then when the user hits next and previous then the listeners in the code will put up on those buttons. I am doing something similar with youTube videos. If you hit next it goes to the end of the youtube video and fires a video complete event tag and then I load the next video when that is called, so that the video will one loop without the next button and two the users can hit the buttons. I have not found a way to monitor the buttons in the player on the iphone side, but if I find it I will post that as well since it is important to know both angels if possible.
Funny thing I think I am looking to try and do the same exact thing. I know how to transition the videos to the next without having to leave the fullscreen mode because of using youTube api in the js but I am not able to observe the quicktime player itself and need to for another feature that I would like to work on.
That's the native iOS player which is a thin version of Quicktime. You'll know if it's an HTML5 player when it doesn't transition from the Quicktime player and your page in Safari. How is your movie being embedded?
I recently had a similar problem and was unable to find a solution using the HTML player. I ended up implementing the video player using MPVideoPlayer Framework and launching it from my web view with a custom URL scheme (AppName:Commnad:Asset). I was then able to use the delegate methods to monitor user interactions. If you would like to see basic implementation, let me know and I can add some code.