Description
FFMPEG 및 shaka-packager를 이용한 dash 인코딩 및 패키징 스크립트
How to Use
Dependencies
- python3 (3.6이상)
- ffmpeg
- h-264 codec
- shaka-packager
Using
파일에서 shaka-packer 경로를 수정해야 함
$ python3 encode_mpd.py video_path.mp4
Packaging completed successfully. 두번 나와야함
./dest_video_path/live, ./dest_video_path/ondemand 폴더에 mpd 파일 및 비디오 세그먼트가 생성됨
Test
index.html
<video autoplay="autoplay" preload="none" controls="true">
<source src="./dest_video_path/live/video_path_live_manifest.mpd" type="application/dash+xml">
</video>
<video autoplay="autoplay" preload="none" controls="true">
<source src="./dest_video_path/ondemand/video_path.mpd" type="application/dash+xml">
</video>
Reference
- Media encoding (https://google.github.io/shaka-packager/html/tutorials/encoding.html)
- DASH packaing (https://google.github.io/shaka-packager/html/tutorials/dash.html)
Example
ffmpeg only.
ffmpeg -re -i glass.mp4 -map 0 -map 0 -c:a aac -c:v libx264
-b:v:0 800k -b:v:1 300k -s:v:1 320x170 -profile:v:1 baseline
-profile:v:0 main -bf 1 -keyint_min 120 -g 120 -sc_threshold 0
-b_strategy 0 -ar:a:1 22050 -use_timeline 1 -use_template 1
-window_size 10 -adaptation_sets "id=0,streams=v id=1,streams=a"
-seg_duration 33
-f dash ./manifest/glass_120_win10_dur33/glass_manifest.mpd
ffmpeg & shaka packager.
1) encoding
ffmpeg -y -i glass.mp4 -c:a aac -ac 2 -ab 256k -ar 48000 -c:v libx264 -x264opts 'keyint=24:min-keyint=24:no-scenecut' -b:v 1500k -maxrate 1500k -bufsize 1000k -vf scale=-1:720 -strict -2 ./sample/sample720.mp4
ffmpeg -y -i ./sample/sample.mp4 -c:a aac -ac 2 -ab 128k -ar 44100 -c:v libx264 -x264opts 'keyint=24:min-keyint=24:no-scenecut' -b:v 800k -maxrate 800k -bufsize 500k -vf scale=-1:540 -strict -2 ./sample/sample540.mp4 -strict -2
ffmpeg -y -i ./sample/sample.mp4 -c:a aac -ac 2 -ab 64k -ar 22050 -c:v libx264 -x264opts 'keyint=24:min-keyint=24:no-scenecut' -b:v 400k -maxrate 400k -bufsize 400k -vf scale=-1:360 -strict -2 ./sample/sample360.mp4 -strict -2
ffmpeg -i glass.mp4 -c:v libvpx-vp9 -keyint_min 150 \
-g 150 -tile-columns 4 -frame-parallel 1 -dash 1 \
-an -vf scale=160:90 -b:v 250k -dash 1 video_160x90_250k.mp4 \
-an -vf scale=320:180 -b:v 500k -dash 1 video_320x180_500k.mp4 \
-an -vf scale=640:360 -b:v 750k -dash 1 video_640x360_750k.mp4 \
-an -vf scale=640:360 -b:v 1000k -dash 1 video_640x360_1000k.mp4 \
-an -vf scale=1280:720 -b:v 1500k -dash 1 video_1280x720_1500k.mp4
- vp9 video en/de coder는 webm용
ffmpeg -y -i ./glass.mp4 -c:a aac -ac 2 -ab 256k -ar 48000 -c:v libx264 -x264opts 'keyint=24:min-keyint=24:no-scenecut' -b:v 1500k -maxrate 1500k -bufsize 1000k -vf scale=-1:720 -strict -2 ./glass_720.mp4
ffmpeg -y -i ./glass.mp4 -c:a aac -ac 2 -ab 128k -ar 44100 -c:v libx264 -x264opts 'keyint=24:min-keyint=24:no-scenecut' -b:v 800k -maxrate 800k -bufsize 500k -vf scale=854:480 -strict -2 ./glass_480.mp4 -strict -2
ffmpeg -y -i ./glass.mp4 -c:a aac -ac 2 -ab 64k -ar 22050 -c:v libx264 -x264opts 'keyint=24:min-keyint=24:no-scenecut' -b:v 400k -maxrate 400k -bufsize 400k -vf scale=640:360 -strict -2 ./glass_360.mp4 -strict -2
encoding: https://google.github.io/shaka-packager/html/tutorials/encoding.html
H264
| scale | profile | level | minrate & maxrate & bufsize & bitrate & output |
|-|-|-|-|-|
360 | baseline | 3.0 | 600k |
480 | main | 3.1 | 1000k |
720 | main | 4.0 | 3000k |
1080 | high | 4.2 | 6000k |
frame rate: 24, GOP size: 72 (3s)
packager https://google.github.io/shaka-packager/html/tutorials/dash.html
static-live stream
packager
'in=h264_baseline_360p_600.mp4,stream=audio,init_segment=audio/init.mp4,segment_template=audio/$Number$.m4s'
'in=input_text.vtt,stream=text,init_segment=text/init.mp4,segment_template=text/$Number$.m4s'
'in=h264_baseline_360p_600.mp4,stream=video,init_segment=h264_360p/init.mp4,segment_template=h264_360p/$Number$.m4s'
'in=h264_main_480p_1000.mp4,stream=video,init_segment=h264_480p/init.mp4,segment_template=h264_480p/$Number$.m4s'
'in=h264_main_720p_3000.mp4,stream=video,init_segment=h264_720p/init.mp4,segment_template=h264_720p/$Number$.m4s'
'in=h264_high_1080p_6000.mp4,stream=video,init_segment=h264_1080p/init.mp4,segment_template=h264_1080p/$Number$.m4s'
--generate_static_live_mpd --mpd_output h264.mpd
on-demand
- creates 4 single track fragmented mp4 streams, a subtitle file and a manifest, which describes the streams.
- ../shaka_packager/src/out/Release/packager
input=./glass_720.mp4,stream=audio,output=./dest/sample720_audio.mp4
input=./glass_720.mp4,stream=video,output=./dest/sample720_video.mp4
input=./glass_360.mp4,stream=audio,output=./dest/sample360_audio.mp4
input=./glass_360.mp4,stream=video,output=./dest/sample360_video.mp4
--profile on-demand
--mpd_output ./manifest/sample-manifest-full.mpd
--min_buffer_time 3
--segment_duration 3
ffmpeg -i glass.mp4 -c:a copy
-vf "scale=640:360"
-c:v libx264 -profile:v baseline -level:v 3.0
-x264-params scenecut=0:open_gop=0:min-keyint=72:keyint=72
-minrate 600k -maxrate 600k -bufsize 600k -b:v 600k
-y h264_baseline_360p_600.mp4
ffmpeg -i glass.mp4 -c:a copy
-vf "scale=854:480"
-c:v libx264 -profile:v main -level:v 3.1
-x264-params scenecut=0:open_gop=0:min-keyint=72:keyint=72
-minrate 1000k -maxrate 1000k -bufsize 1000k -b:v 1000k
-y h264_main_480p_1000.mp4
ffmpeg -i glass.mp4 -c:a copy
-vf "scale=1280:720"
-c:v libx264 -profile:v main -level:v 4.0
-x264-params scenecut=0:open_gop=0:min-keyint=72:keyint=72
-minrate 3000k -maxrate 3000k -bufsize 3000k -b:v 3000k
-y h264_main_720p_3000.mp4
ffmpeg -i glass.mp4 -c:a copy
-vf "scale=1920:1080"
-c:v libx264 -profile:v high -level:v 4.2
-x264-params scenecut=0:open_gop=0:min-keyint=72:keyint=72
-minrate 6000k -maxrate 6000k -bufsize 6000k -b:v 6000k
-y h264_high_1080p_6000.mp4
결과 코드
import subprocess
import sys
shaka_packager = '/mnt/c/Users/heuser/work/shaka_packager/src/out/Release/packager'
options_list = [
# resolution, size, profile, level, bitrate(minrate, maxrate, bufsize, bitrate)
['360', '640:360', 'baseline', '3.0', '1000k'],
['480', '854:480', 'main', '3.1', '1000k'],
['720','1280:720', 'main', '4.0', '3000k'],
['1080', '1920:1080', 'high', '4.2', '6000k']
]
def encode_video_h264():
for opts in options_list:
resolution, size, profile, level, bitrate = opts[:]
out_video = in_video + '_' + resolution
encoded_file_list.append(out_video)
args = ['ffmpeg', '-i', in_video+'.mp4', '-c:a', 'copy', '-vf', 'scale='+size, '-c:v', 'libx264',
'-profile:v', profile, '-level:v', level, '-x264-params', 'scenecut=0:open_gop=0:min-keyint=72:keyint=72',
'-minrate', bitrate, '-maxrate', bitrate, '-bufsize', bitrate, '-b:v', bitrate,
'-y', out_video+'.mp4']
subprocess.run(args)
def make_mpd_ondemand():
args = [shaka_packager,
f'in={in_video}.mp4,stream=audio,output=./dest_{in_video}/ondemand/audio_{in_video}.mp4']
for val in encoded_file_list:
args.append(f'in=./{val}.mp4,stream=video,output=./dest_{in_video}/ondemand/seg_{val}.mp4')
args += ['--mpd_output', './dest_'+in_video+'/ondemand/'+in_video+'_ondemand_manifest.mpd']
subprocess.run(args)
def make_mpd_live():
args = [shaka_packager,
f'in={in_video}.mp4,stream=audio,init_segment=./dest_{in_video}/live/audio/init.mp4,segment_template=./dest_{in_video}/live/audio/$Number$.m4s']
for val in encoded_file_list:
args.append(f'input=./{val}.mp4,stream=video,init_segment=./dest_{in_video}/live/{val}/init.mp4,segment_template=./dest_{in_video}/live/{val}/$Number$.m4s')
args += ['--generate_static_live_mpd', '--mpd_output', './dest_'+in_video+'/live/'+in_video+'_live_manifest.mpd']
subprocess.run(args)
if len(sys.argv) < 2:
print('Use: python3 make_mpd.py [video_file_path.mp4]')
else:
video_path = sys.argv[1]
in_video = video_path.split('/')[-1].split('.mp4')[0]
encoded_file_list = []
encode_video_h264()
make_mpd_ondemand()
make_mpd_live()
'Media' 카테고리의 다른 글
node.js 비디오 비교하기 (0) | 2023.02.03 |
---|---|
node.js HTTP 분할 다운로드 서버 (0) | 2023.02.03 |
bittorrent 정리 (0) | 2023.02.03 |