ryanheise / just_audio

Audio Player
1.04k stars 672 forks source link

[WEB] Dynamic headers for HLS player and Amazon S3 #313

Open BartusZak opened 3 years ago

BartusZak commented 3 years ago

Is your feature request related to a problem? Please describe. I use Amazon S3 (secured) to store my HLS files (.m3u8/ .aac). just_audio allows only to provide one, the same header for all files underneath.

Describe the solution you'd like Implement dynamic headers per .aac file with sigV4 headers (different header per .aac file)

Describe alternatives you've considered Use Amazon Signed Url

Additional context https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html#private-content-overview-choosing-duration

ryanheise commented 3 years ago

Hi @BartusZak

That link didn't specifically talk about HLS, so would you be able to point me to something HLS specific? Is it a feature of another HLS player that you can point me to?

If not, can you propose an API design that would satisfy your use case?

BartusZak commented 3 years ago

Hey @ryanheise,

Thanks for very fast response.

I will prepare a design and get back to you.

ryanheise commented 3 years ago

One concern I have is if no existing audio player library supports this, then it may not be feasible. just_audio is built upon lower level audio player APIs and those themselves need to be able to support this if just_audio is to. The underlying player engine on the platform side takes over complete control of HLS loading with no way to control it. One exception being certain DRM standards.

ryanheise commented 3 years ago

Any update on this?

alexgrusu commented 3 years ago

What do you use as HLS server? Does aws provide a HLS server to stream music?

BartusZak commented 3 years ago

@alexgrusu

As a POC I created .aac and .m3u8 files with AWS Elemental MediaConvert from a few .mp3 files.

Then I uploaded them to Private Amazon S3 Bucket. Now I am trying to receive them from Flutter WEB .

There is more services you can look at: image

@ryanheise I described the way I construct Signed Request Headers for Amazon S3 (https://github.com/ryanheise/just_audio/issues/304#issuecomment-815624048).

The entry point for inserting source audio is like follows:


    _playlist = ConcatenatingAudioSource(
        children: await Future.wait(widget.audiobook!.content!
            .map(
              (content) async => AudioSource.uri(
                  Uri.parse(widget.audiobook!.url! + content!.file!),
                  headers: await _s3Repository!.generateSignedHeaders(
                      widget.audiobook!.url! + content.file!),
                  tag: AudioMetadata(
                      title: content.title, artwork: widget.audiobook!.cover)),
            )
            .toList()));

I uses SigV4 package to calculate headers but there is a official package from AWS team https://github.com/aws-amplify/amplify-flutter.

There is an IF statement to handle .m3u8 already, so there is no sense to create another API. Request Headers and HLS support for web is needed for my case.

BartusZak commented 3 years ago

Hey @ryanheise How are you?

Is there any chance to get request headers working on WEB?

djsjr commented 3 years ago

My need seems to overlap if not be the same. I am using signed URLs with Amazon Cloudfront to serve HLS audio. I already have a method for obtaining the signature, but It requires that "the video [or audio] player will need to be modified to append the signature to every request for a fragment."

Eg. "https://xyz.cloudfront.net/fragement.aac?Policy=SIGNEDURL"

for example with videoJs:

videojs.Hls.xhr.beforeRequest = function (options) {
      options.uri = `${options.uri}${videojs.getAllPlayers()[0].options().token}`;
      return options;
};

Is this possible with just_audio?

ryanheise commented 3 years ago

@djsjr if it's not the same feature, I'd suggest you open a separate feature request. The present issue is about headers.

vanderke commented 7 months ago

I believe that you can accomplish what you need by having AWS Cloudfront generate the required signature inside of all of your .m3u8 files that are served from AWS. It basically modifies the files that you get back from Cloudfront with a signed URL. This allows access to the files for your application, while keeping the files secured behind Cloudfront. By using this method, you don't need to have the headers present, you can just include the Signed URL in the initial request, and everything else will be handled by the Lambda function that is a part of your Cloudfront distribution.

I believe this is why none of the other flutter players support headers either. It would appear that you (and I) have been trying to modify the fragment at the wrong point in the stream. Fix the URL at the source instead of in the client.

I hope this helps!