Skip to content

Instantly share code, notes, and snippets.

@WoonHaKim
Last active January 15, 2020 17:37
Show Gist options
  • Save WoonHaKim/82e6c576e49f4d19addd45ead260ddc0 to your computer and use it in GitHub Desktop.
Save WoonHaKim/82e6c576e49f4d19addd45ead260ddc0 to your computer and use it in GitHub Desktop.
Functions for ffmpeg bundling
import sys
import subprocess
import os
import video_cmds
task_id = sys.argv[1]
src_s3_path = sys.argv[2]
dst_s3_path = sys.argv[3]
file_max_length = 300
working_directory = "/tmp/decode/" + task_id
os.makedirs(working_directory)
video_cmds.sync_aws_s3(src_s3_path, working_directory)
slice_files = os.listdir(working_directory)
slice_files.sort()
os.makedirs(working_directory + "/hls")
last_slice_sec = video_cmds.detect_black_frames(
working_directory + "/" + slice_files[len(slice_files) - 1],
working_directory + "/blackdetect",
)
total_length = (len(slice_files) - 1) * file_max_length + last_slice_sec - 1
output_length_string = video_cmds.convert_seconds_to_timecode(total_length)
print(output_length_string)
video_cmds.generate_input_file_list(slice_files, working_directory + "/input")
video_cmds.ffmpeg_merge(working_directory + "/input", working_directory + "/output.ts")
video_cmds.ffmpeg_range(
working_directory + "/output.ts",
"00:00:01",
output_length_string,
working_directory + "/cut.ts",
)
data = video_cmds.ffmpeg_hls_convert(
working_directory + "/cut.ts", working_directory + "/hls"
)
video_cmds.hls_playlist_file(working_directory + "/hls")
video_cmds.sync_aws_s3(working_directory + "/hls", dst_s3_path + "/hls")
video_cmds.cmd_popen("rm -rf %s" % (working_directory))
import subprocess
import math
default_config = [
{
"height": 480,
"audio_rate": 128,
"min_rate": 1400,
"max_rate": 1498,
"buf_size": 2100,
},
{
"height": 720,
"audio_rate": 128,
"min_rate": 2800,
"max_rate": 2996,
"buf_size": 4200,
},
{
"height": 1080,
"audio_rate": 192,
"min_rate": 5000,
"max_rate": 5350,
"buf_size": 7500,
},
]
def cmd_popen(cmd):
data = subprocess.Popen(cmd, stderr=subprocess.STDOUT, shell=True).wait()
return data
def cmd_check_output(cmd):
data = subprocess.check_output(cmd, shell=True)
return data
def sync_aws_s3(src, dst):
cmd = "aws s3 sync %s %s" % (src, dst)
print(cmd)
data = cmd_popen(cmd)
return data
def detect_black_frames(file, dst="blackdetect.txt"):
cmd = (
'ffmpeg -i %s -vf "blackdetect=d=2:pix_th=0.05" -an -f null - 2>&1 | grep blackdetect > %s'
% (file, dst)
)
print(cmd)
data = cmd_popen(cmd)
start_time = 0
if data == 0:
f = open(dst, "r")
while True:
line = f.readline()
if not line:
break
if "blackdetect" in line:
start_black_string = line.split()[3].split(":")[1]
start_time = round(float(start_black_string))
else:
continue
f.close()
return start_time
else:
return 0
def convert_seconds_to_timecode(sec):
hours = math.floor(sec / 3600)
mins = math.floor(sec / 60)
secs = sec % 60
return "%02d:%02d:%02d" % (hours, mins, secs)
def generate_input_file_list(files, dst):
file_string = ""
for file in files:
if file_string == "":
file_string = file_string + "file %s" % file
if file_string != "hls":
file_string = file_string + "\nfile %s" % file
with open(dst, "w") as f:
f.write(file_string)
def ffmpeg_merge(input_file_list, dst):
cmd = "ffmpeg -f concat -i %s -c copy %s" % (input_file_list, dst)
print(cmd)
data = cmd_popen(cmd)
return data
def ffmpeg_range(src, start, duration, dst):
cmd = "ffmpeg -i %s -ss %s -t %s -c copy %s" % (src, start, duration, dst)
print(cmd)
data = cmd_popen(cmd)
return data
def ffmpeg_hls_convert(src, dst="/tmp/hls", hls_configs=default_config):
config_cmd = ""
for hls_config in hls_configs:
print(hls_config)
height = hls_config["height"]
config_cmd = (
config_cmd
+ "-vf scale=-2:%d -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 4 -hls_playlist_type vod -b:v %dk -maxrate %dk -bufsize %dk -b:a %dk -hls_segment_filename %s/%dp_%s %s/%dp.m3u8 "
% (
height,
hls_config["min_rate"],
hls_config["max_rate"],
hls_config["buf_size"],
hls_config["audio_rate"],
dst,
height,
"%04d.ts",
dst,
height,
)
)
cmd = "ffmpeg -hide_banner -y -i %s -max_muxing_queue_size 9999 %s" % (
src,
config_cmd,
)
print(cmd)
data = cmd_popen(cmd)
return data
def hls_playlist_file(dst, hls_configs=default_config):
file_string = "#EXTM3U\n#EXT-X-VERSION:3"
for hls_config in hls_configs:
file_string = file_string + "\n#EXT-X-STREAM-INF:BANDWIDTH=%d\n%sp.m3u8" % (
hls_config["min_rate"] * 1000,
hls_config["height"],
)
with open(dst + "/playlist.m3u8", "w") as f:
f.write(file_string)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment