RenderHeads / UnityPlugin-AVProVideo

AVPro Video is a multi-platform Unity plugin for advanced video playback
https://www.renderheads.com/products/avpro-video/
231 stars 28 forks source link

Is it possible to cache an HLS video that needs an HTTP Auth token in Android/iOS? #1220

Open brunogalerani opened 2 years ago

brunogalerani commented 2 years ago

Describe the issue I'm trying to cache some HLS protected videos in mobile platforms (Android/iOS). I'm able to create a custom HTTP Header and play these protected videos by setting some keys and cookies, but using the exactly same parameters for the header in mediaPlayer.Cache.AddMediaToCache(url, headers, options) throws a 403 error as response code.

I'd like to know if this feature is already available for these platforms.

Your Setup (please complete the following information):

To Reproduce

  1. Execute the app in an Android/iOS device
  2. Try caching a video protected by Authorization Keys and Cookies
  3. Fails

Logs If applicable, add error logs to help explain your problem. E/DownloadManager: Task failed: null:/content/hls/.../.../***.m3u8, false com.google.android.exoplr2avp.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 403 at com.google.android.exoplr2avp.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:404) at com.google.android.exoplr2avp.upstream.TeeDataSource.open(TeeDataSource.java:52) at com.google.android.exoplr2avp.upstream.cache.CacheDataSource.openNextSource(CacheDataSource.java:786) at com.google.android.exoplr2avp.upstream.cache.CacheDataSource.open(CacheDataSource.java:599) at com.google.android.exoplr2avp.upstream.StatsDataSource.open(StatsDataSource.java:84) at com.google.android.exoplr2avp.upstream.DataSourceInputStream.checkOpened(DataSourceInputStream.java:99) at com.google.android.exoplr2avp.upstream.DataSourceInputStream.open(DataSourceInputStream.java:62) at com.google.android.exoplr2avp.upstream.ParsingLoadable.load(ParsingLoadable.java:174) at com.google.android.exoplr2avp.upstream.ParsingLoadable.load(ParsingLoadable.java:84) at com.google.android.exoplr2avp.offline.SegmentDownloader$1.doWork(SegmentDownloader.java:313) at com.google.android.exoplr2avp.offline.SegmentDownloader$1.doWork(SegmentDownloader.java:310) at com.google.android.exoplr2avp.util.RunnableFutureTask.run(RunnableFutureTask.java:125) at com.renderheads.AVPro.Video.-$$Lambda$_14QHG018Z6p13d3hzJuGTWnNeo.execute(Unknown Source:0) at com.google.android.exoplr2avp.offline.SegmentDownloader.execute(SegmentDownloader.java:353) at com.google.android.exoplr2avp.offline.SegmentDownloader.getManifest(SegmentDownloader.java:309) at com.google.android.exoplr2avp.offline.SegmentDownloader.download(SegmentDownloader.java:136) at com.google.android.exoplr2avp.offline.DownloadManager$Task.run(DownloadManager.java:1347)

Ste-RH commented 2 years ago

What format does 'headers' take that you are passing into 'AddMediaToCache' ? Can you send it over? (you can cut the token part short for security if you desire.

brunogalerani commented 2 years ago

@Ste-RH I've tried a lot of formats, but wasn't able to achieve the caching yet. The latest one was using the RenderHeads' HttpHeaderData.ToValidatedString( ). It's: Cookie:CloudFront-Signature=****; Path=/; HttpOnly; CloudFront-Policy=***; Path=/; HttpOnly; CloudFront-Key-Pair-Id=***; Path=/; HttpOnly;

Ste-RH commented 2 years ago

That might be an issue, but the primary problem is that this is currently an unsupported feature by AVPro Video...which is due to it being an unsupported feature by ExoPlayer. This can be seen here. ExoPlayer does not allow specifying headers per download...rather you can only set a general header when the download manager is initialised.

In short, downloading/caching header protected streams (usually AES) is something we cannot support on Android at this time.

brunogalerani commented 2 years ago

Hey @Ste-RH! Thank for the quick reply.

Is there a way in AVPro to set this general header? It would probably solve my issue if this is possible, but couldn't find anything related to this yet.

brunogalerani commented 2 years ago

Also, is there any fixes for iOS as well?

Ste-RH commented 2 years ago

Hey @Ste-RH! Thank for the quick reply.

Is there a way in AVPro to set this general header? It would probably solve my issue if this is possible, but couldn't find anything related to this yet.

I suppose we could set the download header on each video open as a general rule of thumb (Android only). I will test this and get back to you.

Ste-RH commented 2 years ago

Yeah, that appears to work (within the obvious boundaries/limitations). I will get it in for the next release.

The (string) header is passed in the following format. Key and value pairs are colon separated, with pairs on their own line.

e.g.

key1:value1
key2:value2
key3:value3

Using the HttpHeaderData class and ToValidatedString will put it into this format.

brunogalerani commented 2 years ago

That's awesome! Thank you so much @Ste-RH! I'll be looking forward for the next release!

And about the iOS, it seems to be able to finish downloading the video with the header, but it's not able to play it. I'm looking for anything in the logs that can help to understand this issue!

brunogalerani commented 2 years ago

@Ste-RH is there any expectations for when this next release is coming? The team that I'm working with is really considering buying AVPro for our project, but we'd really need this feature in order to do it so.

Ste-RH commented 2 years ago

We are aiming for 'this week'.

Ste-RH commented 2 years ago

RE iOS. Are you using headers to protect the content, or is the content encrypted (or both I guess).

If the former only, then this should work on iOS. If the content is encrypted, then this is not currently supported on iOS. We will add it onto the 'to investigate if we can offer this functionality' list.

brunogalerani commented 2 years ago

The content is encrypted 😢

Thank you so much for adding it to the list and for all your help as well!

brunogalerani commented 2 years ago

Hey, I've just found something that may help playing encrypted videos in iOS. I'll share the link to the stackoverflow because there's a reasonable amount of information there.

https://stackoverflow.com/questions/45670774/playing-offline-hls-with-aes-128-encryption-ios

Hope this can help to provide some information that leads to a fix for iOS. Sorry if this is a known content already.

brunogalerani commented 2 years ago

Hello!

Sorry to bother, but any news about iOS?

Thank you!

Chris-RH commented 2 years ago

Hi @brunogalerani . Its not been implemented for iOS yet. Its down as a future enhancement, but unlikely to be near-future I'm afraid.