#/**************************************************************************
#* ffmpeg_hys.py: ffmpeg cases options on windows
# python 3.x, ffmpeg-4.3.1
#***************************************************************************
#* Copyright (c) 2020-2020 Hybase@qq.com
#*
#* Author: hybase@qq.com QQ:23207689 WebChat: hybase
#* http://blog.csdn.net/zymill
#* http://github.com/zymill
#*
#* This program is free software: you can redistribute it and/or modify
#* it under the terms of the GNU General Public License as published by
#* the Free Software Foundation, either version 3 of the License, or
#* (at your option) any later version.
#*
#* This program is distributed in the hope that it will be useful,
#* but WITHOUT ANY WARRANTY; without even the implied warranty of
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#* GNU General Public License for more details.
#*
#*****************************************************************************
#* Last update Date: 2020-12-14 19:30:25 version: 0.0.4
#*****************************************************************************
#*/
import os
import re
import sys
import logging
from logging import handlers
################################ logger ######################################
class Logger(object):
level_relations = {
'debug':logging.DEBUG,
'info':logging.INFO,
'warning':logging.WARNING,
'error':logging.ERROR,
'crit':logging.CRITICAL
}
def __init__(self, filename, level='info', when='D', backCount=3, fmt='%(asctime)s-%(pathname)s[line:%(lineno)d] - [%(levelname)s]%(message)s'):
self.logger = logging.getLogger(filename)
format_str = logging.Formatter(fmt)
self.logger.setLevel(self.level_relations.get(level))
sh = logging.StreamHandler()
sh.setFormatter(format_str)
th = handlers.TimedRotatingFileHandler(filename=filename,when=when,backupCount=backCount,encoding='utf-8')
th.setFormatter(format_str)
self.logger.addHandler(sh)
self.logger.addHandler(th)
################################################################################
# Methods check dir/file
def traverseDir(root_path, file_list, dir_list):
dir_or_files = os.listdir(root_path)
for dir_file in dir_or_files:
dir_file_path = os.path.join(root_path, dir_file)
if os.path.isdir(dir_file_path):
dir_list.append(dir_file_path)
traverseDir(dir_file_path, file_list, dir_list)
else:
file_list.append(dir_file_path)
############################################################
# ffmpeg run by os.system()
def ffmpeg_run(log, cmd, run_flag, case_name):
if (run_flag):
log.logger.info('=== start === : ' + case_name)
os.system(cmd)
log.logger.info('=== end === : ' + case_name)
return
log.logger.info('=== by pass === case not setting : ' + case_name)
return
############################################################
# ffmpeg run by os.system()
# format: ffmpeg -y -i e:/material/tt.mkv -filter_complex "vf_str" -vcodec libx264 -acodec aac -f mp4 "output_filename"
def ffmpeg_vf_run(log, vf_str, output_filename, run_flag, case_name):
if (run_flag):
cmd = 'ffmpeg ' + log_param + input_mkv_file + ' -filter_complex ' + vf_str + ' -max_muxing_queue_size 256 -vcodec libx264 -acodec aac -f mp4 ' + output_filename
log.logger.info('=== start === : ' + case_name)
log.logger.info('exec: ' + cmd)
os.system(cmd)
log.logger.info('=== end === : ' + case_name)
return
log.logger.info('=== by pass === case not setting : ' + case_name)
return
############################################################
# ffmpeg run by os.system()
# format: ffmpeg -y -i e:/material/tt.mkv -filter_complex "af_str" -vcodec copy -acodec aac -f mp4 "output_filename"
def ffmpeg_af_run(log, af_str, output_filename, run_flag, case_name):
if (run_flag):
cmd = 'ffmpeg ' + log_param + input_mkv_file + ' -filter_complex ' + af_str + ' -max_muxing_queue_size 256 -vcodec copy -acodec aac -f mp4 ' + output_filename
log.logger.info('=== start === : ' + case_name)
log.logger.info('exec: ' + cmd)
os.system(cmd)
log.logger.info('=== end === : ' + case_name)
return
log.logger.info('=== by pass === case not setting : ' + case_name)
return
################################################################################
# 通用参数字符串
# 统一的输入参数,本文以常见的mkv(H264+AAC)格式为测试素材
# (其中部分需要用到的mpegts文件,采用它派生的tt.ts)
# 测试前的准备工作
# 1)PC 上有 D、E 分区
# 2)E分区上准备下面 mkv/mp4/ts 源文件: 推荐格式为 H264+AAC
# 3)准备拼接需要的hls分片至少 5片,名称及目录:
# E:\material\ffmpeg_hys_python\hls_part\h264_part0.ts
# E:\material\ffmpeg_hys_python\hls_part\h264_part1.ts
# E:\material\ffmpeg_hys_python\hls_part\h264_part2.ts
# E:\material\ffmpeg_hys_python\hls_part\h264_part3.ts
# E:\material\ffmpeg_hys_python\hls_part\h264_part4.ts
# e:/material/ffmpeg_hys_python/hls_part/hls_concat.txt
# hls_concat.txt文件每行内容格式描述一个分片绝对路径,如下所示共5片:
# file 'file:E:/material/ffmpeg_hys_python/hls_part/h264_part0.ts'
# file 'file:E:/material/ffmpeg_hys_python/hls_part/h264_part1.ts'
# file 'file:E:/material/ffmpeg_hys_python/hls_part/h264_part2.ts'
# file 'file:E:/material/ffmpeg_hys_python/hls_part/h264_part3.ts'
# file 'file:E:/material/ffmpeg_hys_python/hls_part/h264_part4.ts'
# 4)准备图片转视频所需的序列化png图片(1000左右),背景MP3音频
# 5) d分区,创建输出目录 d:/otest/ d:/otest/png d:/otest/jpg
tt_src_dir = 'e:/material/ffmpeg_hys_python'
log_param = ' -loglevel info '
input_mkv_file = ' -y -i ' + tt_src_dir + '/tt.mkv '
input_mp4_file = ' -y -i ' + tt_src_dir + '/tt.mp4 '
input_ts_file = ' -y -i ' + tt_src_dir + '/tt.ts '
input_mp3_file = ' -i ' + tt_src_dir + '/es_mp3.mp3 '
input_png_file = ' -f image2 -i ' + tt_src_dir + '/image/image-%03.png '
hls_cancat_file= tt_src_dir + '/hls_part/hls_concat.txt '
################################################################################
# case flags: (default: the first be set, please set others by yourself)
flag_mkv2mp4 = True
flag_mkv2mpegts = False
flag_mkv2flv = False
flag_mpegts2mp4 = False
flag_trc_libx264_aac_mkv2mp4 = False
flag_trc_libx265_aac_mkv2mp4 = False
flag_trc_h264_nvenc_mkv2mp4 = False
flag_trc_hevc_nvenc_mkv2mp4 = False
flag_trc_libx264_mpegts_cbr = False
flag_cut_by_time = False
f