Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ios][expo-av] HLS downloaded multiple times #19296

Open
hirbod opened this issue Sep 29, 2022 · 6 comments
Open

[ios][expo-av] HLS downloaded multiple times #19296

hirbod opened this issue Sep 29, 2022 · 6 comments

Comments

@hirbod
Copy link
Contributor

hirbod commented Sep 29, 2022

Summary

After getting a hint at Twitter and also doing some checks in the network profiler + my CDN, I confirmed that expo-av consumes a lot of bandwidth. Turns out its this:

// We prepare three items for AVQueuePlayer, so when the first finishes playing,
// second can start playing and the third can start preparing to play.
AVPlayerItem *firstplayerItem = [AVPlayerItem playerItemWithAsset:avAsset];
AVPlayerItem *secondPlayerItem = [AVPlayerItem playerItemWithAsset:avAsset];
AVPlayerItem *thirdPlayerItem = [AVPlayerItem playerItemWithAsset:avAsset];
self.items = @[firstplayerItem, secondPlayerItem, thirdPlayerItem];
self.player = [AVQueuePlayer queuePlayerWithItems:@[firstplayerItem, secondPlayerItem, thirdPlayerItem]];

Expo-Av prepares 3x the same item. I don't know the purpose of this, but without a proper HLS Cache, this is not good. I think this has some historical reason (guess: fast looping?). Anyway, I would like to know if we should remove this at all.

What platform(s) does this occur on?

iOS

Environment

Minimal reproducible example

// We prepare three items for AVQueuePlayer, so when the first finishes playing,
// second can start playing and the third can start preparing to play.
AVPlayerItem *firstplayerItem = [AVPlayerItem playerItemWithAsset:avAsset];
AVPlayerItem *secondPlayerItem = [AVPlayerItem playerItemWithAsset:avAsset];
AVPlayerItem *thirdPlayerItem = [AVPlayerItem playerItemWithAsset:avAsset];
self.items = @[firstplayerItem, secondPlayerItem, thirdPlayerItem];
self.player = [AVQueuePlayer queuePlayerWithItems:@[firstplayerItem, secondPlayerItem, thirdPlayerItem]];

@hirbod hirbod added the needs validation Issue needs to be validated label Sep 29, 2022
@hirbod
Copy link
Contributor Author

hirbod commented Sep 29, 2022

Some more infos: its not a big deal with mp4 with my tests, since mp4 caches, but its a big thing with HLS, because it does not cache and always re-request

@brentvatne brentvatne changed the title [ios][expo-av] Huge bandwidth consumption [ios][expo-av] HLS downloaded multiple times Sep 30, 2022
@mnightingale
Copy link
Contributor

I looked into this in the past as far as I can remember as you guessed the AVQueuePlayer with repeated AVPlayerItem's was a historic technique to achieve seamless looping.

It could now be replaced with a AVPlayerLooper (it has an option to disable looping) which was added in iOS 10 and also likely fixes a few reported expo-av issues such as repeated sounds #19198

Side note that I'm not sure if AVPlayerLooper would actually resolve any issue with HLS not being cached, maybe iOS will keep some HLS chunks in memory but I don't think it'll keep significant amounts cached.
There is documentation here about iOS techniques for downloading HLS content for offline playback but it seems to get a bit complicated dealing with different qualities.

@hirbod
Copy link
Contributor Author

hirbod commented Oct 4, 2022

I think a HLS cache would be out of scope right now. It's pretty complicated (but should eventually be integrated when dealing with loop someday). I know that react native video is working on this currently but not sure if it's really reliable.

Integrating AVPlayerLooper seems to be the right choice today, so we could try to fix this bandwidth issue while still being able to loop seamlessly .

@mnightingale
Copy link
Contributor

I don't think AVPlayerLooper will actually resolve your issue, as far as I can gather it basically handles for you what the old method was doing, creates three AVPlayerItems and loops through them.

I do think what you really need is video caching, but I'm not sure if even react-native-video can handle that for HLS.

@hirbod
Copy link
Contributor Author

hirbod commented Oct 7, 2022

From my research, it might need https://developer.apple.com/documentation/avfoundation/avassetcache
But the real question is: how does it work under the hood, how does it handle multiple qualities and bitrates etc, and how long does it keep stuff cached? And will it be cached into memory or to disk, how long will it stay there etc.

More information:
https://developer.apple.com/documentation/avfoundation/offline_playback_and_storage/using_avfoundation_to_play_and_persist_http_live_streams

@brentvatne brentvatne added Video Issue accepted and removed needs validation Issue needs to be validated labels Nov 26, 2022
@expo-bot
Copy link
Collaborator

Thank you for filing this issue!
This comment acknowledges we believe this may be a bug and there’s enough information to investigate it.
However, we can’t promise any sort of timeline for resolution. We prioritize issues based on severity, breadth of impact, and alignment with our roadmap. If you’d like to help move it more quickly, you can continue to investigate it more deeply and/or you can open a pull request that fixes the cause.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants