只有一个 mp4 文件的 MPEG-DASH 视频流
MPEG-DASH video stream with just single mp4 file
我研究了一个星期,以找到一种简单且独立于平台的方法来将 mp4 文件流式传输到任何浏览器。如果浏览器不兼容,将使用渐进式流(直接下载)方法。我的场景是这样的:
- 单个mp4文件(未分段和复用(音频+视频))
- 支持 HTTP 字节范围服务
- 在浏览器不兼容的情况下支持渐进式流(直接文件下载)
在研究了 Apple HLS、Adobe Flash Stream、Microsoft Smooth、RTSP 和 MPEG-DASH 之后,MPEG-DASH 似乎是正确的解决方案。但问题是 MPEG-DASH 迫使我将 mp4 文件拆分为单独的分段文件,这导致 duplicate 消耗 space 来存储 mp4 文件,因为我必须支持渐进式流浏览器不兼容的情况。然后将单个 mp4 文件与分段的 mp4 文件一起存储是不可避免的。
问题是:有没有办法将单个 mp4 文件作为http 流[=43] =] & 在任何浏览器中的渐进流 ?
MPEG-DASH 协议说它支持多路复用文件,但问题是 dash.js 不支持它。是否有任何其他 javascript 播放器支持具有字节范围请求的多路复用和单个 mp4 文件?
欢迎提交符合我的场景条件的任何其他解决方案。
谢谢
参考资料:
BitCodin.com 1
BitCodin.com 2
是的,有解决办法。 dash.js只播放打包好的mp4碎片。然而,Telecom Paristech 的 Cyril 的这个项目将做你想做的事:
https://github.com/gpac/mp4box.js/
这是mp4box的js版本。它可以做的是将非碎片化的 mp4 即时转换为媒体片段,然后可以将其馈送到 MSE sourceBuffer。他们有一个可以执行此操作的示例播放器,您可以复制它:
http://download.tsi.telecom-paristech.fr/gpac/mp4box.js/
干杯
会
我认为所有主流浏览器都支持 mp4。 http://caniuse.com/#feat=mpeg4。您可以只使用一个很好的旧 http 服务器来流式传输它。 MPEG-DASH
仅当您需要自适应比特率流、多语言、drm 等花哨的东西时才需要。
如果您坚持使用 MPEG-DASH
,您可以在服务器端使用 mp4box 简单地对您的 mp4 文件进行分段(您只需执行一次)。结果不是多个 mp4 文件,而是一个以更适合流媒体方式组织的 mp4 文件。
您可以使用单个 mp4 文件为 dash 播放器提供服务。但是,您需要将索引信息放入此 mp4 文件的 sidx 框中。你可以做便当。实际上对于点播情况,通常是使用单个文件进行流式传输。您也可以在本地下载此文件。
如果您只有一种比特率,则 Dash 流式传输不需要更多的存储空间。并且有很多 javascript 播放器支持 dash,例如 shakashaka 播放器、dashif 播放器...
也许这对你有帮助:
#!/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"
我研究了一个星期,以找到一种简单且独立于平台的方法来将 mp4 文件流式传输到任何浏览器。如果浏览器不兼容,将使用渐进式流(直接下载)方法。我的场景是这样的:
- 单个mp4文件(未分段和复用(音频+视频))
- 支持 HTTP 字节范围服务
- 在浏览器不兼容的情况下支持渐进式流(直接文件下载)
在研究了 Apple HLS、Adobe Flash Stream、Microsoft Smooth、RTSP 和 MPEG-DASH 之后,MPEG-DASH 似乎是正确的解决方案。但问题是 MPEG-DASH 迫使我将 mp4 文件拆分为单独的分段文件,这导致 duplicate 消耗 space 来存储 mp4 文件,因为我必须支持渐进式流浏览器不兼容的情况。然后将单个 mp4 文件与分段的 mp4 文件一起存储是不可避免的。
问题是:有没有办法将单个 mp4 文件作为http 流[=43] =] & 在任何浏览器中的渐进流 ?
MPEG-DASH 协议说它支持多路复用文件,但问题是 dash.js 不支持它。是否有任何其他 javascript 播放器支持具有字节范围请求的多路复用和单个 mp4 文件?
欢迎提交符合我的场景条件的任何其他解决方案。 谢谢
参考资料: BitCodin.com 1 BitCodin.com 2
是的,有解决办法。 dash.js只播放打包好的mp4碎片。然而,Telecom Paristech 的 Cyril 的这个项目将做你想做的事:
https://github.com/gpac/mp4box.js/
这是mp4box的js版本。它可以做的是将非碎片化的 mp4 即时转换为媒体片段,然后可以将其馈送到 MSE sourceBuffer。他们有一个可以执行此操作的示例播放器,您可以复制它:
http://download.tsi.telecom-paristech.fr/gpac/mp4box.js/
干杯 会
我认为所有主流浏览器都支持 mp4。 http://caniuse.com/#feat=mpeg4。您可以只使用一个很好的旧 http 服务器来流式传输它。 MPEG-DASH
仅当您需要自适应比特率流、多语言、drm 等花哨的东西时才需要。
如果您坚持使用 MPEG-DASH
,您可以在服务器端使用 mp4box 简单地对您的 mp4 文件进行分段(您只需执行一次)。结果不是多个 mp4 文件,而是一个以更适合流媒体方式组织的 mp4 文件。
您可以使用单个 mp4 文件为 dash 播放器提供服务。但是,您需要将索引信息放入此 mp4 文件的 sidx 框中。你可以做便当。实际上对于点播情况,通常是使用单个文件进行流式传输。您也可以在本地下载此文件。 如果您只有一种比特率,则 Dash 流式传输不需要更多的存储空间。并且有很多 javascript 播放器支持 dash,例如 shakashaka 播放器、dashif 播放器...
也许这对你有帮助:
#!/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"