shaka-project / shaka-player

JavaScript player library / DASH & HLS client / MSE-EME player
Apache License 2.0
7.11k stars 1.33k forks source link

How to append signed url parameters to base urls from manifest file #443

Closed ajbeach2 closed 8 years ago

ajbeach2 commented 8 years ago

So, I am trying to figure out how to append signed url parameters to the requests for some MPEG-DASH streams. For now, the manifest files (.mpd) are NOT signed. However, when the manifest is parsed, the base url's are parsed form the manifest file. Those base URLS, in the manifest, need to be signed. Basically, we will make an additional request to our API which will generate the signatures for those base urls.

Is there a way to do this with plugins? or do I need to create another manifest parser plugin?

joeyparrish commented 8 years ago

We should have a tutorial that focuses on this particular requirement, but we do have an API for this and it is documented.

If you look at the License Server Authentication tutorial, there's an example of registerRequestFilter().

To modify the URL for manifest requests, you would register a request filter, watch for type == shaka.net.NetworkingEngine.RequestType.MANIFEST, then modify the request.uris Array. If there are multiple URIs in the array, NetworkingEngine will use them for fallback should one fail.

The request filter is synchronous, so you will need to either compute your signature in advance or be able to compute it synchronously in the filter callback.

Does this help?

ajbeach2 commented 8 years ago

Thanks I will look into that. The signed URL parameter generation is asynchronous though. Our API server contains our AWS credentials that sign the stream url's so that they expire, I think we need to generate those when the manifest is parsed.

ajbeach2 commented 8 years ago

In my use case, lets say, that the .mpd file has a base url that is something like http://mybucket.s3.amazonaws.com/files/movie.mp4. The signed url would be something like: http://mybucket.s3.amazonaws.com/files/movie.mp4?Signature=123123123123123. The license server in this case is really our API sever that returns that second url, which the player would need to use to get the stream.

In the tutorial, you have this for parameter authentication, which I am not sure fits the above use case. Is there a request type for the media files?

var manifestUri = '//storage.googleapis.com/shaka-demo-assets/sintel-widevine/dash.mpd';
var licenseServer = '//cwip-shaka-proxy.appspot.com/param_auth';
  player.getNetworkingEngine().registerRequestFilter(function(type, request) {
    // Only add headers to license requests:
    if (type == shaka.net.NetworkingEngine.RequestType.LICENSE) {
      // This is the specific parameter name and value the server wants:
      request.uris[0] += '?CWIP-Auth-Param=VGhpc0lzQVRlc3QK';
    }
  });
joeyparrish commented 8 years ago

Ah, you want to sign your segment URLs, not your manifest. I misunderstood. You can change the segment URLs by filtering for RequestType.SEGMENT.

But since you need to make an async call to generate the signatures, a request filter won't work for you.

One solution would be to modify NetworkingEngine to allow request filters to operate asynchronously. For backward compatibility, a filter that is done could still return nothing. But a filter returning a Promise would only be complete when the Promise was resolved.

However, this would have you signing each segment right before it was requested, adding latency to each segment download while you wait for the round-trip to the signing server. Does each segment require a different signature, or could you just make one signing request early on and use it for all segments in that manifest?

ajbeach2 commented 8 years ago

I would have to see how exactly amazon signs the URLs but I believe the hash function that generates the Signature URL parameter includes the domain for each asset. So the signature parameter would be different for every url in the manifest.

The signatures are created server side, so I suppose it could just be an additional json blog returned with the path to the mpd file when that video is request. This means however, the mpd needs to be parsed both client side and server side, which is less than ideal. But yeah I could modify the networkengine to async get a signature for every baseurl.

ajbeach2 commented 8 years ago

I am going to close this because I have the information that I need.