ryanheise / just_audio

Audio Player
1.02k stars 625 forks source link

DRM Support #468

Open tinusneethling opened 2 years ago

tinusneethling commented 2 years ago

Add DRM Support.

Is your feature request related to a problem? Please describe. Yes, DRM support needed for certain content licensing.

Describe the solution you'd like Implement a generic DRM framework.

Describe alternatives you've considered N/A

Additional context I have already implemented a generic DRM framework with a first implementation of ClearKey for Android.

ryanheise commented 2 years ago

On Android, fortunately everything can be done through the ExoPlayer APIs, and I would be in favour of exposing those APIs through the just_audio API, simplifying where it makes sense. On iOS I would also prefer the same approach using FairPlay. Then, a generic API can be built on top of that.

Although if we create a generic DRM API, then it would need to at least recognise that there are different DRM options on Android vs iOS.

tinusneethling commented 2 years ago

This is exactly the way implemented. A map is created for DRM similar to the header map in the UriAudioSource class. I have created a DRMHelper class that generate the properties for the various DRM schemas. I have implemented ClearKey DRM already for Android.

On Mon, Aug 2, 2021 at 11:14 AM ryanheise @.***> wrote:

On Android, fortunately everything can be done through the ExoPlayer APIs, and I would be in favour of exposing those APIs through the just_audio API, simplifying where it makes sense. On iOS I would also prefer the same approach using FairPlay. Then, a generic API can be built on top of that.

Although if we create a generic DRM API, then it would need to at least recognise that there are different DRM options on Android vs iOS.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ryanheise/just_audio/issues/468#issuecomment-890865239, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOCPMVTJQ53OJZ4EC2FSONLT2ZOWRANCNFSM5BMJECWQ .

ryanheise commented 2 years ago

Hi @tinusneethling that sounds promising. I know people who are looking forward to DRM so this is definitely a feature worth having. Do you have a GitHub repo to share so I can take a look (or a pull request)?

tinusneethling commented 2 years ago

Hi, I have created the below pull request.

https://github.com/ryanheise/just_audio/pull/472

ryanheise commented 2 years ago

I look forward to reviewing it :+1:

tinusneethling commented 2 years ago

I have mistakenly worked from the master branch. I have incorporated all of your comments and created a new pull request to dev branch. DRM Support #477

rupakswadesh commented 2 years ago

When i am playing a song after that i closed the app but song still playing in background and now again open the app then last activity showing issue? I wanna that when app start then data reload.

ryanheise commented 2 years ago

@rupakswadesh , are you saying that the DRM support pull request mentioned above specifically is causing the issue for you?

tinusneethling commented 2 years ago

@rupakswadesh, i have tested and can't replicate. Can you please confirm if you are running from the pull request?

ryanheise commented 2 years ago

It was probably an unrelated question ;-) I will hide these comments.

ryanheise commented 2 years ago

I think the platform interface still needs some careful thought to make it future proof, since I have worked on projects before where some customisation was required (via these callbacks) to work with the particular license server. It is reasonable to only support a subset of functionality now, but with some forethought about future expansion.

What I think I'll do is create a new branch for DRM development which can allow people to use it while it's in development, while also giving it time before stablising and publishing.

tinusneethling commented 2 years ago

I have again looked at the better_player implementation where the callbacks are not implemented. If you perhaps can provide me with the use case I can look at implementing? I see better_player has extended certain functionality but the interface as is should be able to cater.

I do think rotating keys were left on implementation of callbacks but subsequently this is handled directly by ExoPlayer.

ryanheise commented 2 years ago

The use case was a custom widevine server, so requesting the license needed to be customised. But as mentioned, I'm not looking at implementing this now. I just want to ensure we have a solid foundation.

Probably the main thing I would look at now is introducing a typed data structure to replace the map, since all messages in just_audio that are sent through the platform channel are implemented in a typesafe manner:

class AndroidDrmConfiguration extends DrmConfiguration {
  final Uri licenseUri;
  final ....;
}

Later, a DarwinDrmConfiguration could be added, hence having a DrmConfiguration superclass.

Now, obviously a different config object would be needed for each platform. So when passing in the drm parameter to each audio source, the question is whether it would be better for the app to conditionally pass in the correct drm config depending on the current platform, or whether it would be better for the AudioSource API to allow passing in a separate parameter for each platform's DRM config and then let the plugin itself contain the conditional code. (Not sure if I explained that well.)

Thoughts?

tinusneethling commented 2 years ago

I initially implemented on the basis of creating a DrmConfiguration and then creating superclass for each implementation. The superclass should not be platform specific but rater the actual DRM. Examples of superclasses could be ClearKeyDRM, FairplayDRM, WidewineDRM, CustomDRM. Certain DRM work only specific platforms but some are shared(for example WEB).

The DrmConfiguartion should contain method toMap().

When the AudioSourceMessage is created the toMap() should be call as per below:

@override AudioSourceMessage _toMessage() => ProgressiveAudioSourceMessage( id: _id, uri: _effectiveUri.toString(), headers: headers, tag: tag, drm: drm.?toMap(), ); //so a map is still passed when create the AudioSourceMessage object and platform code remains as is.

If you are agreaable then I will update the code as per below and remove the DRMHelper class. Or do you want to create equivalent message classes in the interface package as you have do for AudioSource? Might be to much for just DRM?

ryanheise commented 2 years ago

My comment above is really just to consider what would be the most convenient way to help app developers manage different configurations that they're likely to use per platform, because apps will typically use a different DRM solution for Android and iOS. Either the API should make that convenient, or the documentation should tell them how to handle this use case. I guess this would be most similar to the audio effects which are different per platform. I anticipated there might be an audio effect that is identical on both platforms and so I set up the superclasses as mixins which allows for a sort of multiple inheritance, so that the same audio effect could be passed into both the Android pipeline and the iOS pipeline.

Yes I do think each of these objects should have the appropriate toMessage/toMap methods etc, and this may also help to address the other issue that it is less complicated from a license and copyright perspective to write new code rather than copy code. Since you mentioned the above project, I looked and noticed this block of code has lost its author history in the git logs due to probably a squash merge, so the just_audio LICENSE file might have a difficult time giving correct attribution for that.

morhi commented 6 months ago

Hey @ryanheise ! I just wanted to ask if you still think about implementing this feature? It seemed like a PR was on they way, but I couldn't really figure out, why this feature got stopped working on. Thanks for your work!

ryanheise commented 6 months ago

I don't remember now but reading my previous comment as a refresher, it looks like the API needed some refinement so that typed data was sent across the platform interface rather than an untyped map. Also, I can't remember whether this was the case, but I seem to be suggesting a copyright issue with the code.

tinusneethling commented 5 months ago

Good Morning,

Yes I would like to implement it as I had to create a branch which I need to merge constantly. There are no copyright issues with this and standard DRM decoder supported by Android.

I see you have released a new version with some changes to ProgressiveAudioSource.

I think it would be best to add an optional argument to ProgressiveAudioSourceOptions called AndroidClearKeyOptions with a single field clearKey[string]. ClearKey DRM would then only be applied to ProgressiveAudioSources.

Let me know what you think and I will implement it.

Regards,

On Sun, Jan 14, 2024 at 1:25 AM ryanheise @.***> wrote:

I don't remember now but reading my previous comment as a refresher, it looks like the API needed some refinement so that typed data was sent across the platform interface rather than an untyped map. Also, I can't remember whether this was the case, but I seem to be suggesting a copyright issue with the code.

— Reply to this email directly, view it on GitHub https://github.com/ryanheise/just_audio/issues/468#issuecomment-1890792857, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOCPMVU7WETRTROTWE7657TYOMJWHAVCNFSM5BMJECW2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCOBZGA3TSMRYGU3Q . You are receiving this because you were mentioned.Message ID: @.***>

--

Tinus Neethling

C : +27 83 212 6473 M : @.***

[image: signature_270669602]

Infinite Shared Content Systems Inc. 8 The Green, Ste A. Dover, DE 19901, Delaware USA.

Infinite Shared Content Systems Inc. (hereafter ISCS) has updated its Privacy Policy to comply with the General Data Protection Regulation (GDPR) effective 24 May 2018. Emails are processed under Article 6 EU GDPR Lawfulness of Processing. All personal data held by ISCS is held securely and, in most instances, is limited to your First Name, Last Name, Company of Employment and Position held at such Company of Employment. Under no circumstances does ISCS share your personal information with any third party. This e-mail (and any attachments) are confidential and intended solely for the use of the named recipient(s) to whom it is addressed. If you are not the intended recipient(s) please do not disclose, copy or take any action in reliance on it. If you received this message in error, please tell us by email reply and delete all copies on your system. Whilst we have taken reasonable precautions to ensure that any attachment to this e-mail has been swept for viruses, we cannot accept liability for any damage sustained as a result of software viruses. To remove your information from ISCS’s records, please reply to this email with a request to do so.

ryanheise commented 5 months ago

@tinusneethling yes It would be nice to look at this again.

My view on using a map structure vs typed classes and subclasses for each DRM type is that a map might be easier to maintain, but typed classes would be more consistent with what I have done elsewhere in the platform interface. Although before moving forward, can you think of any aspects to DRM that are actually better suited to a map vs typed classes?

tinusneethling commented 5 months ago

Hi,

I think a combination of the two would be best. Will use classes on the dart side with a generic DRM map to be sent through on the platform interface.(If possible I could look at using one of the existing maps to avoid bumping the interface package)? Parameters can then be extended without touching the interface package later.

Can then apply DRM to any of the MediaSource.Factory factories which should allow for extending on a case by case basis.

Let me know what you think?

Regards,

On Thu, Feb 1, 2024 at 11:19 AM ryanheise @.***> wrote:

@tinusneethling https://github.com/tinusneethling yes It would be nice to look at this again.

My view on using a map structure vs typed classes and subclasses for each DRM type is that a map might be easier to maintain, but typed classes would be more consistent with what I have done elsewhere in the platform interface. Although before moving forward, can you think of any aspects to DRM that are actually better suited to a map vs typed classes?

— Reply to this email directly, view it on GitHub https://github.com/ryanheise/just_audio/issues/468#issuecomment-1920865742, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOCPMVXO34T2YMHJL74BFHLYRNM2ZAVCNFSM5BMJECW2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCOJSGA4DMNJXGQZA . You are receiving this because you were mentioned.Message ID: @.***>

--

Tinus Neethling

C : +27 83 212 6473 M : @.***

[image: signature_270669602]

Infinite Shared Content Systems Inc. 8 The Green, Ste A. Dover, DE 19901, Delaware USA.

Infinite Shared Content Systems Inc. (hereafter ISCS) has updated its Privacy Policy to comply with the General Data Protection Regulation (GDPR) effective 24 May 2018. Emails are processed under Article 6 EU GDPR Lawfulness of Processing. All personal data held by ISCS is held securely and, in most instances, is limited to your First Name, Last Name, Company of Employment and Position held at such Company of Employment. Under no circumstances does ISCS share your personal information with any third party. This e-mail (and any attachments) are confidential and intended solely for the use of the named recipient(s) to whom it is addressed. If you are not the intended recipient(s) please do not disclose, copy or take any action in reliance on it. If you received this message in error, please tell us by email reply and delete all copies on your system. Whilst we have taken reasonable precautions to ensure that any attachment to this e-mail has been swept for viruses, we cannot accept liability for any damage sustained as a result of software viruses. To remove your information from ISCS’s records, please reply to this email with a request to do so.

ryanheise commented 4 months ago

I'm very sorry, this issue got lost in a stack of browser tabs, sorry about that!

Regarding the decision about passing an untyped map vs defining typed interfaces, I've decided I would prefer consistency with the existing code base with a typed interface. I would be happy to code up the platform interface part of this, to make that approach go more smoothly.

The other thing, and i think we discussed this briefly last time, was to make sure the API is future compatible with, say, later supporting Widevine. Not now of course, but there at least needs to be room in the API design for a future effort to slot in.

Looking at this page, Widevine is expected to be a fair bit more complicated in terms of API implications, I'm not sure if you feel so, too, or whether you think it can also neatly fit into an untyped map-based solution.

ryanheise commented 4 months ago

Also note that people who use a Widevine product will very likely want to be doing things such as online and offline (cached) licenses. And depending on the vendor, there might be a need for implementing custom callbacks.