2

I'm trying to integrate live-transcoding like "plex" or "emby" with my application.

I am able to serve dash content over to shaka-player or dash.js but only in 'live-mode'. But I want to enable seeking through the player.

I looked at plex and to enable this they create their own mpd file with duration so the player will have a full seekbar.

However when seeking the player will ask for a segment number eg: 449. I need to stop ffmpeg and restart with an offset (-ss <<segment * sgement_length>>), but ffmpeg will just restart a transcode session from segment 0 with an initial segment.

What I want is to tell ffmpeg to start at a seekpoint but only output from segment number and now-on.

When playing with hls and mpegts, I can tell ffmpeg to output at a certain segment : with the option -segment_start_number but this is not available for dash. And plex use their own transcoder based of ffmpeg with the option -skip_to_segment

I tried to 'hack' around by keeping a manual offset on my web-server, even if I serve the "supposed" right segment after the seek point dash.js and shaka-player can't recover the stream.. VLC on the other habd is able to (probably more tolerent) to errors in segments.

Is the supposed right segment after a seek in dash (contains the initial segment) or only the segment.

Is ffmpeg able to start segmenting dash as a supposed segment (for seek and resume)

The same technique works in hls with forced key frames and a custom m3u8 (with all the "predicted" segments) but calculating the right segment length and the right bandwidth is much harder and hackish and dash is more tolerant to variation.

I would really like to be able to seek through my live transcoding video.

For reference here is a custom mpd file I serve to enable "seeking":

<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="urn:mpeg:dash:schema:mpd:2011"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
    profiles="urn:mpeg:dash:profile:isoff-live:2011"
    type="static"
    suggestedPresentationDelay="PT1S"
    mediaPresentationDuration="PT49M2.920S"
    maxSegmentDuration="PT2S"
    minBufferTime="PT10S">
    <Period start="PT0S" id="0" duration="PT49M2.920S">
        <AdaptationSet segmentAlignment="true">
            <SegmentTemplate timescale="1" duration="1" initialization="$RepresentationID$/initial.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="1">
            </SegmentTemplate>
            <Representation id="0" mimeType="video/mp4" codecs="avc1.640029" bandwidth="3766000" width="1920" height="1080">
            </Representation>
        </AdaptationSet>
        <AdaptationSet segmentAlignment="true">
            <SegmentTemplate timescale="1" duration="1" initialization="$RepresentationID$/initial.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="1">
            </SegmentTemplate>
            <Representation id="1" mimeType="audio/mp4" codecs="mp4a.40.2" bandwidth="188000" audioSamplingRate="48000">
                <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="6"/>
            </Representation>
        </AdaptationSet>
    </Period>
</MPD>

And here is the ffmpeg command to pull it off:

ffmpeg -ss 0 -i movie.mkv -y -acodec aac -vcodec libx264 -f dash -min_seg_duration 1000000 -individual_header_trailer 0 -pix_fmt yuv420p -vf scale=trunc(min(max(iw\,ih*dar)\,1920)/2)*2:trunc(ow/dar/2)*2 -bsf:v h264_mp4toannexb -profile:v high -level 4.1 -map_chapters -1 -map_metadata -1 -preset veryfast -movflags frag_keyframe+empty_moov -use_template 1 -use_timeline 0 -remove_at_exit 1 -crf 23 -bufsize 7532k -maxrate 3766k -start_at_zero -threads 0 -force_key_frames expr:if(isnan(prev_forced_t),eq(t,t),gte(t,prev_forced_t+1)) -init_seg_name $RepresentationID$/0_initial.mp4 -media_seg_name $RepresentationID$/0_$Number$.m4s /transcoding_temp/Z1GVWEc/index.mpd

The media_seg_name is where I prepend the custom seek_point let's say I want to seek to segment 1233 the template would be:

-media_seg_name $RepresentationID$/1233_$Number$.m4s

and the segments would be 1233_1 1233_2 1233_* So I can serve the right segment after seek. but the player does not recover and still downloading subsequent segments. I guess since a new initial segment is generated and I somehow miss headers for continuous playback after seek but I'm probably wrong.

Thanks for your help

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
inkubux
  • 236
  • 2
  • 11
  • After digging this is a presentation time issue as the chunks created with the option `-ss` from ffmpeg are not time shifted so the content of the segment contains a tag of `eareliest_presentation_time` of 0 instead of the time setted by the -`ss` option. Is there a way to fix this other than modifying the segment at a binary level which I don't know how... – inkubux Jan 11 '18 at 03:17
  • Did you end up finding a solution? I'm currently trying to solve the same problem. – woubuc Jul 06 '19 at 13:04

1 Answers1

1

The manifest you are showing is a static one, meaning it is not a live service stream. If you want to enable a client to seek through a live stream which is still running, then you need to define a MPD@timeShiftBufferDepth attribute.

Example dynamic manifest: https://vm2.dashif.org/livesim/testpic_2s/Manifest.mpd

Working with player: http://reference.dashif.org/dash.js/v2.6.4/samples/dash-if-reference-player/index.html?url=https://vm2.dashif.org/livesim/testpic_2s/Manifest.mpd

Maybe use this working example as a reference to figure out where your implementation is different?

Will Law
  • 176
  • 1
  • 1
  • Thanks. I looked a bit on it but it dose not really help me in the sense, my issue is with segment generation, as the dash player does not consider my segment to be at valid presentation time at the moment it ask for it and the player stalls. The timeShiftBufferDepth does in fact provide me a seekbar as well as the static feed. In fact i'm trying to simulate a static file with a transcoder in the background if that does make any sense... – inkubux Jan 09 '18 at 19:21