kaltura / nginx-vod-module

NGINX-based MP4 Repackager
GNU Affero General Public License v3.0
1.99k stars 439 forks source link

How to use mapped+remote mode with dynamic JSON #1097

Open pszemus opened 4 years ago

pszemus commented 4 years ago

Hi I want to concatenate multiple mp4 files in one MPEG-DASH stream.

  1. Is it possible to configure this module in a way that when user requests for /dynamic.json/manifest.mpd nginx will issue a subrequest to http://adserver/dynamic.json that returns different response for different users?
  2. Is it possible to have clip name in clip's chunks names and fragment numbering starting from 1 so that if the same clip is in multiple different JSON reponses it's chunks can be cached and served from standard nginx cache?
pszemus commented 4 years ago

The idea that I have in mind right now:

  1. player asks nginx-vod-module (mapped mode) for MPEG-DASH /manifest.mpd
    1. nginx-vod-module asks http://adserver/dynamic.json for ads for that user
    2. nginx-vod-module receives dynamic.json and generates manifest.mpd
  2. player asks nginx-vod-module (remote mode) for MPEG-DASH chunks: /media/ad1.mp4/fragment-1-v1-x3.m4s
    1. nginx-vod-module asks http://mp4storage/ad1.mp4 for /media/ad1.mp4/fragment-1-v1-x3.m4s

In order it to work:

That way the dynamic.json is requested just once, I could cache all the chunks, and they are immutable regardless of their corresponding mp4 file's position in dynamic.json.

What do you think about that? Chunk numbering and paths could be done in lua module if nginx-vod-module does not have necessary configuration options.

erankor commented 4 years ago

The module outputs continuous timestamps, even in multi-period DASH, so the segments will not be same if they are part of different MPDs. Sounds to me that it may be easiest to have the module perform the segmentation of the media files, and perform the manifest manipulation elsewhere (maybe in some high level language like node.js)

pszemus commented 4 years ago

I prepared a proof-of-concept and it works in Google Shaka Player and MPEG-DASH reference player.

  1. I'm downloading a multi-period manifest from:

        location / {
            vod dash;
            vod_mode mapped;
    
            # location of JSON
            vod_upstream_location /playlist;
    
            # location of source video files
            vod_remote_upstream_location /media-origin;
    
            # TODO:
            # - @media and @initialization attributes should be prefixed with /media/$mp4filename/
            # - @startNumber attribute should be set to 1
            vod_base_url "";
        }
  2. Then I alter the manifest.mpd and change each <Period>'s @startNumber to 1 and set base URL for @initialization and @media attributes to /media/<put mp4 file name here>
  3. Segments are downloaded from /media/:
        location /media/ {
            vod dash;
            vod_mode remote;
            vod_upstream_location /media-origin;
            vod_base_url ""; # relative segment URLs
            rewrite ^/media(.*)$ $1 break;
        }

As I said before, this stream can be played in Google Shaka Player and MPEG-DASH reference player.

Regarding timestamps: In my proof-of-concept, manifests are served via / location (mapped mode) whereas all segments are served via /media/ location (remote mode). I checked segment's sidx/earliest_presentation_time, moof/mfhd/sequence number and moof/traf/tfdt/base media decode time and they are starting from 0 in segment No.1 and they are increasing correctly in latter segments. With segment numbering starting from 1 for every <Period> it is OK to do so, because timestamps also would start from 0 for every <Period>.

To sum up, in order to accomplish dynamic JSON and static segments, nginx-vod-module should have: