MPEG-DASH video stream with just single mp4 file

22,449

Solution 1

I think all major browser support mp4. http://caniuse.com/#feat=mpeg4. You can stream it using just a good old http server. MPEG-DASH is required only if you require fancy stuff like adaptive bitrate streaming, multi language, drm and so.

If you insist on using MPEG-DASH you can simply segment your mp4 files using a mp4box on the server side (you have to do it only once). The result is not mulitple mp4 files but rather a single mp4 files that is organized in a more suitable for streaming way.

Solution 2

Yes there is a solution. dash.js only plays fragmented mp4s that have been packaged. However, this project from Cyril at Telecom Paristech will do what you want:

https://github.com/gpac/mp4box.js/

This is a js version of mp4box. What it can do is on-the-fly conversion of your non-fragmented mp4 in to media fragments which can then be fed to a MSE sourceBuffer. They have a sample player that does this which you can copy:

http://download.tsi.telecom-paristech.fr/gpac/mp4box.js/

Cheers Will

Solution 3

Maybe this would help you:

#!/bin/bash

# THIS SCRIPT CONVERTS EVERY MP4 (IN THE CURRENT FOLDER AND SUBFOLDER) TO A MULTI-BITRATE VIDEO IN MP4-DASH
# For each file "videoname.mp4" it creates a folder "dash_videoname" containing a dash manifest file "stream.mpd" and subfolders containing video segments.
# Explanation: 


# Validation tool:
# https://conformance.dashif.org/

# MDN reference:
# https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery/Setting_up_adaptive_streaming_media_sources

# Add the following mime-types (uncommented) to .htaccess:
# AddType video/mp4 m4s
# AddType application/dash+xml mpd

# Use type="application/dash+xml" 
# in html when using mp4 as fallback:
#                <video data-dashjs-player loop="true" >
#                    <source src="/walking/walking.mpd" type="application/dash+xml">
#                    <source src="/walking/walking.mp4" type="video/mp4">
#                </video>

# DASH.js
# https://github.com/Dash-Industry-Forum/dash.js

MYDIR=$(dirname $(readlink -f ${BASH_SOURCE[0]}))
SAVEDIR=$(pwd)

# Check programs
if [ -z "$(which ffmpeg)" ]; then
    echo "Error: ffmpeg is not installed"
    exit 1
fi

if [ -z "$(which MP4Box)" ]; then
    echo "Error: MP4Box is not installed"
    exit 1
fi

cd "$MYDIR"

TARGET_FILES=$(find ./ -maxdepth 1 -type f \( -name "*.mov" -or -name "*.mp4" \))
for f in $TARGET_FILES
do
  fe=$(basename "$f") # fullname of the file
  f="${fe%.*}" # name without extension

  if [ ! -d "${f}" ]; then #if directory does not exist, convert
    echo "Converting \"$f\" to multi-bitrate video in MPEG-DASH"

    mkdir "${f}"

    ffmpeg -y -i "${fe}" -c:a aac -b:a 192k -vn "${f}_audio.m4a"

    ffmpeg -y -i "${fe}" -preset slow -tune film -vsync passthrough -write_tmcd 0 -an -c:v libx264 -x264opts 'keyint=25:min-keyint=25:no-scenecut' -crf 22 -maxrate 5000k -bufsize 12000k -pix_fmt yuv420p -f mp4 "${f}_5000.mp4"
    ffmpeg -y -i "${fe}" -preset slow -tune film -vsync passthrough -write_tmcd 0 -an -c:v libx264 -x264opts 'keyint=25:min-keyint=25:no-scenecut' -crf 23 -maxrate 3000k -bufsize 6000k -pix_fmt yuv420p -f mp4  "${f}_3000.mp4"
    ffmpeg -y -i "${fe}" -preset slow -tune film -vsync passthrough -write_tmcd 0 -an -c:v libx264 -x264opts 'keyint=25:min-keyint=25:no-scenecut' -crf 23 -maxrate 1500k -bufsize 3000k -pix_fmt yuv420p -f mp4   "${f}_1500.mp4"
    ffmpeg -y -i "${fe}" -preset slow -tune film -vsync passthrough -write_tmcd 0 -an -c:v libx264 -x264opts 'keyint=25:min-keyint=25:no-scenecut' -crf 23 -maxrate 800k -bufsize 2000k -pix_fmt yuv420p -vf "scale=-2:720" -f mp4  "${f}_800.mp4"
    ffmpeg -y -i "${fe}" -preset slow -tune film -vsync passthrough -write_tmcd 0 -an -c:v libx264 -x264opts 'keyint=25:min-keyint=25:no-scenecut' -crf 23 -maxrate 400k -bufsize 1000k -pix_fmt yuv420p -vf "scale=-2:540" -f mp4  "${f}_400.mp4"
    # static file for ios and old browsers
    ffmpeg -y -i "${fe}" -preset slow -tune film -vsync passthrough -write_tmcd 0 -c:a aac -b:a 160k -c:v libx264  -crf 23 -maxrate 2000k -bufsize 4000k -pix_fmt yuv420p -f mp4 "${f}/${f}.mp4"


    rm -f ffmpeg*log*
    # if audio stream does not exist, ignore it
    if [ -e "${f}_audio.m4a" ]; then
        MP4Box -dash-strict 2000 -rap -frag-rap  -bs-switching no -profile "dashavc264:live" "${f}_5000.mp4" "${f}_3000.mp4" "${f}_1500.mp4" "${f}_800.mp4" "${f}_400.mp4" "${f}_audio.m4a" -out "${f}/${f}.mpd"
        rm "${f}_5000.mp4" "${f}_3000.mp4" "${f}_1500.mp4" "${f}_800.mp4" "${f}_400.mp4" "${f}_audio.m4a"
    else
        MP4Box -dash-strict 2000 -rap -frag-rap  -bs-switching no -profile "dashavc264:live" "${f}_5000.mp4" "${f}_3000.mp4" "${f}_1500.mp4" "${f}_800.mp4" "${f}_400.mp4" -out "${f}/${f}.mpd"
        rm "${f}_5000.mp4" "${f}_3000.mp4" "${f}_1500.mp4" "${f}_800.mp4" "${f}_400.mp4" 
    fi
    # create a jpg for poster. Use imagemagick or just save the frame directly from ffmpeg is you don't have cjpeg installed.
    ffmpeg -i "${fe}" -ss 00:00:00 -vframes 1  -qscale:v 10 -n -f image2 - | cjpeg -progressive -quality 75 -outfile "${f}"/"${f}".jpg

    fi

done

cd "$SAVEDIR"

Solution 4

You could serve dash player with single mp4 file. However you need to put index information in sidx box in this mp4 file. you could bento4 to do it. Actually for ondemand case, it's normally to use one single file to stream. You could also download this file locally. Dash streaming will not require more storage size if you only have one bitrate. and there are many javascript player are supporting dash like shakashaka player, dashif player ...

Share:
22,449
Behrouz.M
Author by

Behrouz.M

Forward-thinking and Innovative Senior Software Development adept in the creation, debugging, maintenance, and optimization of software systems and related tools. Dedicated and hardworking with proficiency in various frameworks, platforms, and languages. Highly adaptable, flexible professional who embraces teamwork, but also enjoys working independently.

Updated on July 21, 2020

Comments

  • Behrouz.M
    Behrouz.M almost 4 years

    I'm researching for a week to find a simple and platform independent method to stream a mp4 file to any browser. In case of browser incompatibility progressive stream(direct download) method will be used. My scenario is like this:

    • single mp4 file (not segmented and multiplexed(Audio+Video) )
    • HTTP Byte-Range serving supported
    • progressive stream (direct file download) supported in case of browser incompatibility

    After studying Apple HLS, Adobe Flash Stream, Microsoft Smooth, RTSP and MPEG-DASH it seems that MPEG-DASH is the proper solution. But the problem is MPEG-DASH forcing me to split mp4 file to separate segmented files which leads to duplicate consuming space to store the mp4 file because I have to support progressive stream in case of browser incompatibility. Then storing single mp4 file with segmented mp4 files is unavoidable.

    The question is: is there any way to serve a single mp4 file as http stream & progressive stream in any browser ?

    MPEG-DASH protocols says it supports multiplexed files but the problem is dash.js does not support it. Is there any other javascript player which supports multiplexed and single mp4 files with byte-range requests ?

    Any other solution which commits my scenario conditions is welcomed. Thanks.

    REFERENCES: BitCodin.com 1 BitCodin.com 2

    • Svetlin Mladenov
      Svetlin Mladenov about 8 years
      I think all major browser support mp4. http://caniuse.com/#feat=mpeg4. You can stream it using just a good old http server. MPEG-DASH is required only if you require fancy stuff like adaptive bitrate streaming, multi language, drm and so. I don't completely understand your problem. If you insist on using MPEG-DASH you can simply segment your mp4 files using a mp4box on the server side (you have to do it only once). The result is not mulitple mp4 files but rather a single mp4 files that is organized in a more suitable for streaming way.
    • Behrouz.M
      Behrouz.M about 8 years
      @SvetlinMladenov Thanks. My major problem is Default Android Browsers. I've tested over than 4 different JS Player. None of them played the mp4 file correctly. The mp4 video is played well only in full screen state.
    • Behrouz.M
      Behrouz.M about 8 years
      @SvetlinMladenov I've used HandBrake to encode MP4 files, web optimized & 2-pass encoding. Only in this case Android browsers & Chrome plays the MP4 videos. But the problem is it only works in full screen state. ref: broken-links.com/2010/07/08/…
    • Behrouz.M
      Behrouz.M about 8 years
      @SvetlinMladenov Please post your comment as answer. I want to accept it!
    • Behrouz.M
      Behrouz.M about 8 years
      @SvetlinMladenov I've solved video playing in Android using this post: stackoverflow.com/a/24403519/365229
  • Behrouz.M
    Behrouz.M about 8 years
    Thanks for the answer. It seems nice. Let me check it.
  • Farshid Ashouri
    Farshid Ashouri about 5 years
    @raypixar Sorry if I got the question wrong. Good luck and thanks for +1.
  • Arjun
    Arjun over 4 years
    I'm using ExoPlayer for streaming videos from a firebase database where the mp4 url is stored. The mp4 url is of file location in firebase storage. Everything is working fine except it takes lot of time to load the video. Could you please help me how can I convert the normal mp4 format in DASH format for adaptive bitrate streaming? I have little idea about this, but in a blog post I'd read that DASH is faster way to stream and it'll help reduce the starting loading time. Could you please help me to get some idea for workaround this issue?
  • Arjun
    Arjun over 4 years
    Also ExoPlayer has DASH support, but all I have is a mp4 url how could I use the DASH feature with this URL?
  • Illep
    Illep over 2 years
    Can you explain what the script does and how to run it please?