只有单个 mp4 文件的 MPEG-DASH 视频流

Posted

技术标签:

【中文标题】只有单个 mp4 文件的 MPEG-DASH 视频流【英文标题】:MPEG-DASH video stream with just single mp4 file 【发布时间】:2016-05-16 07:25:32 【问题描述】:

我正在研究一个星期,以找到一种简单且独立于平台的方法,可以将 mp4 文件流式传输到任何浏览器。如果浏览器不兼容,将使用渐进式流(直接下载)方法。我的场景是这样的:

单个 mp4 文件(未分段和多路复用(音频+视频)) 支持 HTTP 字节范围服务 在浏览器不兼容的情况下支持渐进式流(直接文件下载)

在研究了 Apple HLS、Adobe Flash Stream、Microsoft Smooth、RTSP 和 MPEG-DASH 之后,似乎 MPEG-DASH 是正确的解决方案。但问题是 MPEG-DASH 迫使我将 mp4 文件拆分为单独的分段文件,这导致 duplicate 消耗空间来存储 mp4 文件,因为在浏览器不兼容的情况下我必须支持渐进式流。然后将单个 mp4 文件与分段 mp4 文件存储是不可避免的。

问题是:有没有办法将单个 mp4 文件作为http 流渐进式流 在任何浏览器中?

MPEG-DASH 协议说它支持多路复用文件,但问题是dash.js 不支持它。是否有任何其他 javascript 播放器支持具有字节范围请求的多路复用和单个 mp4 文件?

欢迎任何其他符合我的场景条件的解决方案。 谢谢。

参考: BitCodin.com 1 BitCodin.com 2

【问题讨论】:

我认为所有主流浏览器都支持mp4。 http://caniuse.com/#feat=mpeg4。您可以只使用一个好的旧 http 服务器来流式传输它。只有当您需要自适应比特率流、多语言、drm 等花哨的东西时,才需要 MPEG-DASH。我不完全理解你的问题。如果您坚持使用 MPEG-DASH,您可以简单地使用服务器端的 mp4box 对您的 mp4 文件进行分段(您只需执行一次)。结果不是多个 mp4 文件,而是以更适合流式传输的方式组织的单个 mp4 文件。 @SvetlinMladenov 谢谢。我的主要问题是Default android Browsers。我已经测试了超过 4 种不同的 JS 播放器。他们都没有正确播放 mp4 文件。 mp4 视频只有在全屏状态才能正常播放。 @SvetlinMladenov 我使用HandBrake 编码MP4 文件web optimized & 2-pass encoding。只有在这种情况下,Android 浏览器和 Chrome 才会播放 MP4 视频。但问题是它只能在 全屏 状态下工作。参考:broken-links.com/2010/07/08/… @SvetlinMladenov 请发表您的评论作为答案。我愿意接受! @SvetlinMladenov 我已经使用这篇文章解决了 Android 中的视频播放问题:***.com/a/24403519/365229 【参考方案1】:

我认为所有主流浏览器都支持 mp4。 http://caniuse.com/#feat=mpeg4。您可以只使用一个好的旧 http 服务器来流式传输它。仅当您需要自适应比特率流、多语言、drm 等花哨的东西时才需要MPEG-DASH

如果您坚持使用MPEG-DASH,您可以简单地在服务器端使用mp4box 对您的mp4 文件进行分段(您只需执行一次)。结果不是多个 mp4 文件,而是以更适合流式传输的方式组织的单个 mp4 文件。

【讨论】:

我正在使用 ExoPlayer 从存储 mp4 url​​ 的 firebase 数据库流式传输视频。 mp4 url​​ 是 firebase 存储中的文件位置。一切正常,除了加载视频需要花费大量时间。您能否帮助我如何将正常的 mp4 格式转换为 DASH 格式以进行自适应比特率流传输?我对此一无所知,但在一篇博客文章中,我读到 DASH 是一种更快的流式传输方式,它有助于减少开始加载时间。你能帮我想出一些解决这个问题的想法吗? ExoPlayer 也支持 DASH,但我只有一个 mp4 url​​,我怎么能在这个 URL 上使用 DASH 功能?【参考方案2】:

是的,有一个解决方案。 dash.js 仅播放已打包的碎片化 mp4。但是,Telecom Paristech 的 Cyril 的这个项目可以满足您的需求:

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

这是一个js版本的mp4box。它可以做的是将您的非分段 mp4 即时转换为媒体片段,然后可以将其馈送到 MSE sourceBuffer。他们有一个示例播放器,您可以复制它:

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

干杯 会

【讨论】:

感谢您的回答。看起来不错。让我检查一下。【参考方案3】:

也许这会对你有所帮助:

#!/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"

【讨论】:

@raypixar 对不起,如果我的问题弄错了。祝你好运,感谢 +1。 你能解释一下这个脚本的作用以及如何运行它吗?【参考方案4】:

您可以使用单个 mp4 文件为 dash 播放器提供服务。但是,您需要将索引信息放在此 mp4 文件的 sidx 框中。你可以用bento4来做。实际上,对于按需情况,通常使用一个文件进行流式传输。您也可以在本地下载此文件。 如果您只有一种比特率,短跑流将不需要更多的存储空间。还有很多javascript播放器都支持dash,比如shakashaka播放器,dashif播放器...

【讨论】:

以上是关于只有单个 mp4 文件的 MPEG-DASH 视频流的主要内容,如果未能解决你的问题,请参考以下文章

使用 ffmpeg 生成单个 MPEG-Dash 片段

MPEG-DASH 和分段 mp4

如何使用 MPEG DASH 流式传输和捕获 MP4 文件?

具有安全 S3 URL 的 MPEG-Dash

如何使用 MPEG-DASH 流式传输实时视频? [关闭]

如何使 MPEG-DASH 流式传输基于时间片的不同质量