loadSound: don't wait for the entire download before play, but not have it start automatically - actionscript

I am trying to play an MP3 using Actionscript 2. I have the following requirements:
I don't want to wait for the MP3 to load before playing it.
I want to know when enough of the MP3 has downloaded that I can start playing it.
I don't want the MP3 to start playing immediately: I need to control when the play starts.
An example scenario is that I need to start playing a 30-second MP3 exactly 8 seconds from now (at the top of the minute, let's say). Depending on the connection, I may or may not be able to download the entire MP3 by then, but I can almost certainly download enough to start playing without interruption.
The closest way I can see to do this is Sound.loadSound(url, isStreamable). If I pass true for the isStreamable parameter, though, the sound will start playing immediately (docs say: Playback begins when sufficient data has been received to start the decompressor).
I've tried the following:
call mySound.loadSound(mp3Url, true)
mySound.stop(); // so that the auto-play won't happen
set a timer for the top of the minute (8 seconds from now).
In the timer, check the duration of the sound (which continues to get bigger as the file gets loaded). If the duration is < 5 seconds, we don't have enough buffered sound, so generate an error. Otherwise, start playing the sound with s.start(0).
The behavior I see is that the sound doesn't start playing until it's entirely downloaded.

I found your posting (which is a little older now, but... anyway):
there are two options you can use in the Sound-class:
Sound.getBytesTotal
and
Sound.getBytesLoaded
If you compare these two, you can get the amount of bytes loaded at a certain point of time. (See also Sound.onLoad and Sound.onSoundComplete, these two are helpful)
There are also some examples in the Flash help for this.
Greetings,
Draco

I do not believe that this is possible using ActionScript 2. I think you are going to have to either move to AS3 or wrap the MP3 in a SWF.
Even with AS3 you may have to target FP10 in order to use the new sound methods and events that were just added (Sound.extract and Event.SAMPLE_DATA).
In general Sound capabilities in Flash have really lagged until the most recent version of the player.

Related

Release (envelope) cut out when AKsequencer repeats?

I'm using AKSequencer to trigger AKPlayer using a midi note, to repeat certain audio files.
The question I have is that, the audio files are sometimes slightly longer than the designated midi durations, because there are release sounds included in the audio. AKPlayer doesn't seem to continue playing the files at the end of the sequencer duration - it immediately moves onto the new file triggered, so the audio files sound always slightly cut at the end. Slightly awkward.
Is there some sort of option such as 'mute after AKDuration' vs. 'Keep playing once it's triggered'? I am not even sure if this is AKplayer-related, or AK-sequencer-related issue. Thank you so much <3

AudioKit metronome synced with time-pitched audio loops

I'm making an app that plays synced audio loops with a metronome. For example, I might have 3 files like this:
bass_60bpm.m4a
drums_60bpm.m4a
guitar_60bpm.m4a
And a metronome sound tick.m4a, which I play with AKSamplerMetronome.
I need to play them back at arbitrary tempos, so I use AKTimePitcher on the AKAudioFiles (so playing at 90bpm, I'd play bass_60bpm.m4a at 1.5x).
This almost works, but after 3-5 loops, the metronome gets out of sync with the audio loops. I think I understand why that happens (audio_sample_length * floating_point_number is not equivalent to AKSamplerMetronome's tempo calculations), but I don't know how to fix it.
What I suspect I need to do is manually reimplement some or all of AKSamplerMetronome, but play the metronome ticks based on AKTimePitcher's output, but I can't piece together enough info from the API, docs, and examples to make it happen.
An alternate approach might be to use AKSequencer instead of AKSamplerMetronome. The midi output of the sequencer's track could be sent to an AKCallbackInstrument, and the sequencer's events could get the callback function to trigger both the time-stretched sample and the metronome ticks (and you could also trigger synchronized UI events from there as a bonus). This would guarantee that they stay in sync.
Apple's MusicSequence, which is what AKSequencer uses under the hood, is a little flakey with its timing immediately after you call play, but it's pretty solid after that. If you start the sequencer just before its looping point (i.e., if you have a 1 bar loop, start it one sixteenth note before the end of the first bar) then you can get passed that flakiness before the actual loop starts.

Annoying lag when AVQueuePlayer jumps from asset to another

I have an AVQueuePlayer that is supposed to play sequentially an array of AVURLAsset representing consecutive fragments of one continuous video.
Whenever a fragment ends and another starts, there is a small glitch that can be well noticed (frame hold for approx 0.2sec and sound gets muted)
I tried researching how to get around that issue but haven't found anything. I tried solving it by having 2 AVQueuePlayer's and switch between both around 0.2sec before the end of every fragment. Issue not solved.
Any idea on how to solve that?
Note: When joining the mp4 fragments together using an mp4 joiner software, the output is a single smooth video without any glitch.
Been through this exactly. You will experience that glitch no matter what you do. Reason being how AVQueuePlayer works. It loads the next item when the previous ends. So if your videos are big, you may also see that blank screen for 2-3 seconds. One solution is what you mentioned, i.e. using two AVQueuePlayer. But as you said its not working for you, and even if you make it work, it will be clumsy.
A better and clean solution is AVMutableComposition. It may look complex at first but its fast and one time task. You create a composition of all of your videos and play it in a simple AVPlayer. And in your case, I assume you just have to play it, so you don't even have to export it.
To know how to use AVMutableComposition, go through this link. It will explain with exact code you need.
As you said, "2 AVQueuePlayers" way still has problem(some sound glitch).
I faced same problem and solved it by using HLS.
You can play local TS files.
At first, make m3u8 and TS files from original movie file.
e.g.
mediafilesegmenter -t 10 sample.mp4
Then, add resource files to iOS device. You can add files from iTunes, add as resource, or make download function and get from your app.
Run a http server, and then pass the local URL to AVPlayerController. I used cocoaHttpServer.
I put simple example here.
https://github.com/satoshi0212/samples/tree/master/TSPlaySample

How can I stream a movie in iOS and playback from the filesystem later?

I've got an app that currently ships with all the videos it can play embedded in it. This doesn't scale well, and unless you want to play all the movies, wastes disk space. It also makes it less desirable to upgrade the app because you have to re-download all movies.
What I would like to do is download the movie on the fly, play it back while downloading, and then if it's successfully downloaded, save it to the file system so that next time they want to watch it, it streams from the local file.
I can do whatever is needed to the video, but currently I'm serving it up as an .mp4 file from Amazon S3, with a mimetype of video/mp4, and so the first half of my issue works fine: the movie downloads, and MPMovieViewController will start playing it as soon as it thinks it has downloaded "enough."
Is there any way to tap into the cache of that video file so that I can save it and control how long it resides on the filesystem? This seems like it would be the easiest approach.
I am targeting iOS 5+6, but if the only solution available required iOS 6, I would consider it also. Thanks!
UPDATE: Using AFNetworking, I am now half-way there, I think. I am downloading the video file from the server, and listening for the download progress. Once I see 25% of the video has been downloaded, I start playback on the local file using an MPMoviePlayerController.
The main issue I'm running into now is playback seems to get screwed up. It's going along fine, 25% downloaded, playback starts... download continues normally... then the file finishes downloading completely, and shortly thereafter video freezes. The onscreen playback timer still indicates playback is ongoing and I don't see any "playback finished" type notifications, but the video is frozen. My guess based on the behavior is that perhaps the initial buffer for the video playback was used up, and it isn't detecting that more video is available on disk now?
Is there any way to interact with MPMoviePlayerController to let it know periodically to refresh the buffer it's playing out of? Or some other way to handle this situation?
UPDATE: Make sure to see the newer answer from #TomHamming.
I have yet to find a conclusive answer, but at this time I believe the answer is: you can't reliably do this. At least not without a lot of work which seems too much like a hack. I filed a feature request with Apple as it really seems like this should be possible with some adjustments to MPMoviePlayerController.
I will go over the variety of things I tried or considered, and the results I encountered.
Pass MPMoviePlayerController a URL to your movie file, which allows it to stream, and then pull the file out of the cache it was saved into, into your local Documents folder. Won't work, as of iOS 6. I filed a feature request with Apple, but as it stands now there's no way to get your hands on the file they are downloading, AFAIK.
Start downloading the movie file with NSURLConnection (or something like AFNetwork), and then when a "decent amount" has been downloaded to the device, pass the file URL to the MPMoviePlayerController and let it stream from disk. Sort of works, but not well. Three problems:
It's really hard to know when to start playing the file. I haven't figured out the algorithm Apple uses, and so I always erred on the side of caution, waiting for 25% to be downloaded before playing.
The MPMoviePlayerController interface provides no sense of the movie being streamed, as it does when Apple is doing the calculations via the network. It appears to the user that the file is totally downloaded when it really is not.
And most importantly, MPMoviePlayerController seems to not work well with playing a file that is not completely downloaded. I experienced playback problems once the file finished downloading, or if the player caught up with the amount downloaded, and never found a graceful way to handle these situations.
Same procedure as above, but use AVFoundation classes to more finely control the playback process, and avoid the issues described above regarding playback stopping, etc. Might work, but I want all the features of MPMoviePlayerController. Re-implementing MPMoviePlayerController myself just to get this one feature seems like a waste of time.
Same procedure as #1 above, but run a small web server in your app to handle streaming the video from the disk to MPMoviePlayerController, with the hope being that the streaming would work more like it normally does when streaming the file directly from an external web server. Works, but results were still sporadic and performance seemed to suffer. I did my test with CocoaHTTP. I decided against this approach because it just felt like a terrible hack.
Run a lightweight HTTP proxy, thus intercepting the downloaded movie file data as it gets streamed from the internet into your MPMoviePlayerController. Not sure if this works or not. I was not able to test this yet, as I have not found a lightweight HTTP proxy written in Objective-C, and at this point don't feel like implementing one just to try this experiment. It seems like the next easiest of all these hacks to implement -- if you don't have to write the proxy!
At this point I've decided to go the less-hacky, but also less user-friendly route of simply downloading the file completely, and then passing it to MPMoviePlayerController, until a better solution comes along.
You can do this as of iOS 10 with AVAssetDownloadTask. See this WWDC 2016 session and this documentation.
Alternatively, if your movie isn't DRM'd, you can do it with AVAssetResourceLoaderDelegate, which effectively lets you give an AVPlayer an arbitrary stream of bytes. See this walkthrough.

Skip between multiple files while playing audio in iPhone iOS

For a project I need to handle audio in an iPhone app quite special and hope somebody may point me in the right direction.
Lets say you have a fixed set of up to thirty audio files of the same length (2-3 sec, non-compressed). While a que is playing from one audio file it should be able to update parameters that makes the playing continue from another audio file from the same timestamp the previous audiofile ended playing. If the different audio files is different versions of heavely filtered audio it should be possible to "slide" between them an get the impression that you applied the filter directly. The filtering is at the moment not possible to achive in realtime on an iPhone, therefore the prerendered files.
If A B and C is different audio files I like to be able to:
Play A without interruption:
Start AAAAAAAAAAAAA Stop
Or start play A and continue over in B and then C, initiated while playing
Start AAABBBBBBBBCC Stop
Ideally is should be possible to play two er more ques at the same time. Latency is not that important, but the skipping between files should ideally not produce clicks or delays.
I have looked into using Audio Queue Services (which look like hell to dive into) and sniffed on OpenAl. Could anyone give me a ruff overview and a general direction I can spend the next days burried into?
Try using the iOS Audio Unit API, particularly a mixer unit connected to RemoteIO for audio output.
I managed to do this by using FMOD Designer. FMOD (http://www.fmod.org/) is a sound design framework for game development, that supports iOS development. I made a multitrack-event in FMOD Designer with different layers for each sound clip. Add a parameter in the horizontal bar that lets you controll which sound clip to play in realtime. The trick is to let each soundclip continue over the whole bar and controll which sound that is beeing heard by using a volume effect (0-100%) like in the attached picture. In that way you are ensured that skipping between files follow the same timecode. I have tried this successfully with up to thirty layers, but experienced some double playing. This seemed to dissapear if I cut the number down to fifteen.
It should be possible to use iOS Audio Unit API if you are comfortable with this, but for those of us that like the most simple sollution FMOD is quite good :) Thanks to Ellen S for the sollution tip!
Screenshot of the multitrack-event in FMOD Designer:
https://plus.google.com/photos/106278910734599034045/albums/5723469198734595793?authkey=CNSIkbyYw8PM2wE

Resources