AVPlayer and Progressive Video Downloads with AVURLAssets
Asked Answered
A

1

11

We've got an app we're working on that needs to provide playback of video files via AVPlayer. The files need to be stored on the user's device, but also must playback while downloading.

At the moment we've built a download module that uses the ASIHTTPRequest library to get the video files via PHP (we don't want the media to be linkable via public URLs) and write them to disk asynchronously.

We've then setup an AVPlayer as per the AV Foundation Programming Guide, getting the file with AVURLAsset, making an AVPlayerItem with the asset, building the AVPlayer with the item, then setting the player to an AVPlayerLayer. The player runs fine with a fully downloaded video file and will also run a progressively downloaded file perfectly well in the simulator.

Unfortunately on an actual device, the behavior of the player changes, where instead it seemingly loads the video once and doesn't attempt to grab new packets from disk. The result is that the player will play video and audio up to the point in the video that marks where the download progress was at the time the asset was loaded (e.g. if 2MB of data are buffered then the player is created, the player will only play up to the 2MB worth of data). Because it has the video's header, the player will happily continue thinking it's playing for the full duration of the video, but no other video is rendered to screen.

The last wrinkle is that if the video is inserted into an AVComposition and the AVPlayer is created with that, the progressive video will play fine. This would be a fine solution (and is necessary for our app anyway on occasion) except that the client for our app requires that the video be playable on an Apple TV via AirPlay, which AVCompositions are incapable of.

Does anyone know if there is a way to play progressively downloading video files using an AVPlayer built from AVURLAssets? Is there a way to force the player/playerItem to read from disk with an AVURLAsset the way it seems to do with an AVComposition instead of seemingly caching the video in memory?

Thanks!

Almena answered 12/2, 2013 at 23:6 Comment(8)
Did you ever work through this issue? What version of iOS were you on and did this behavior change with more recent version(s)?Gautama
No, I still don't have a solution for this other than to use AVComposition. We were using iOS 5.1 and 6.0 at the time and the behaviour continues still through 6.1.Almena
@RobertNall I'm trying to do the same thing you are with AVComposition - can you elaborate a bit how exactly you inserted the video into AVComposition? If the player reaches EOF, does the playback resume after more data is downloaded?Ardent
@Jai - I don't recall the details off-hand, but I believe we simply made an AVURLAsset out of the file as it was downloading and AVComposition will happily play whatever's there. When it reaches the end of the so-far-downloaded data it will leave the last frame it had access to and will continue to "play" until it reaches the length (time-wise) of the video. We had to roll our own buffering system, trying to approximate the time it would take to download the whole video and holding off playback until we felt the download would finish before the playback did.Almena
(cont.) If the player does reach the end of the data (but not the end of the video), it won't auto-pause/resume. However, if you detect it and pause it manually, you can resume the player after more data has been downloaded and it will play the newly downloaded data. Hope that helps!Almena
@RobertNall thanks yeah just realized that as long as EOF leads the playback progress all is fine. Now I just need to detect EOF before the player hits it - let me know if you have any ideas on how to do that, will research and see too.Ardent
@RobertNall I'm facing this kind of issue recently, I try to download video using NSURLConnection, and save it to mp4 to disk. Play the video while downloading, The first few seconds works fine, but if the player plays to the end of video, and haven't download data from server yet, the player stops, and it wont resume...Have you solved this problem yet? Can you share your solution? Thank youChaffin
I'm sorry, I didn't see the comment on the top, it seems there already have a solution, I'll give it a try!Chaffin
J
6

I haven't a solution to just make it work wit AVURLAssets but I use a slightly different approach. We bundle our App with CocoaHTTPServer and play video files which aren't fully downloaded trough a HTTP request against the local server.

The server knows the total length of the file and can then decide by looking at the HTTP-Headers which part of the file is request and either loads it from disk or from remote source.

While developing this there where always 3 initial requests, one for the first two bytes of the file, one of a larger chunk from the beginning of the file and one chunk directly of the end of the file. That's why it was always needed to load at least the last part directly from the remote server since the player would need it right from the start. I would guess the same happens for local files so the player loads the last bytes from the file (which aren't the right last bytes) and won't play over that length.

You would have to subclass HTTPConnection and make your own HTTPResponse class by looking at the provided "HTTPAsyncFileResponse".

I hope this gives you an idea how to accomplish this with a different approach.

Jadotville answered 13/2, 2013 at 12:46 Comment(4)
When you get the response that contains the final chunk of the file, are you writing empty bytes between the beginning and the end so that the player has the ending bytes in the right place?Almena
I only write to disk what fits to the actual size of the file, so chunks from the beginning will be written to the disk. But the request to the end won't be it's just returned to the player.Jadotville
Thinking about this again, you might also try something like this: aptogo.co.uk/2010/07/protecting-resources but instead the crypto stuff you could implement the reading/writing from remote/local.Jadotville
Hey Soph, even I don't feel I can mark this as a full answer to the question, I still wanted to say thanks for spending the time to offer some suggestions. For now we're just dealing with the AVComposition and forgoing the Airplay stuff...Almena

© 2022 - 2024 — McMap. All rights reserved.