技术标签: python 视频技术 数值解析 ffmpeg实例 ffmpeg hybase 编程细节
以下是ffmpeg执行转码记录到文件的日志,为了能分析转码结果,其中PSNR,平均码率等数值是比较常用的参数,为了能快速提前结果,本文提供了一个python的处理样例,请参考后续代码。
[email protected] http://blog.csdn.net/zymill
================== start ====================
ffmpeg version 4.4 Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-11)
configuration: --enable-shared --enable-static --enable-version3 --enable-gpl --enable-nonfree --enable-libfdk-aac --enable-libmp3lame --enable-libx264 --enable-libx265 --enable-libxvid --enable-libdavs2 --enable-libxavs2 --enable-libdav1d --enable-libuavs3d --enable-cuda --enable-libnpp --enable-cuvid --enable-ffnvcodec --enable-nvenc --enable-nvdec --enable-zlib --enable-libfribidi --enable-libfreetype --enable-libxml2 --enable-fontconfig --enable-libass --enable-frei0r --enable-opengl --enable-filter=gltransition --extra-libs='-lGLEW -lglfw3' --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64
libavutil 56. 70.100 / 56. 70.100
libavcodec 58.134.100 / 58.134.100
libavformat 58. 76.100 / 58. 76.100
libavdevice 58. 13.100 / 58. 13.100
libavfilter 7.110.100 / 7.110.100
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100
Input #0, mpegts, from '/home/ffmpeg-4.4.x/ai_trc_shfiles/nobody_hls/nobody_00001.ts':
Duration: 00:00:04.67, start: 6.822000, bitrate: 4077 kb/s
Program 1
Metadata:
service_name : hys Dec 22 2021 17:52:49_s01
service_provider: hys
Stream #0:0[0x100]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 90k tbn, 47.95 tbc
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
Press [q] to stop, [?] for help
[libx264 @ 0x15ad340] --psnr used with psy on: results will be invalid!
[libx264 @ 0x15ad340] --tune psnr should be used if attempting to benchmark psnr!
[libx264 @ 0x15ad340] using SAR=1/1
[libx264 @ 0x15ad340] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 AVX512
[libx264 @ 0x15ad340] profile High, level 4.0, 4:2:0, 8-bit
[mpegts @ 0x1591380] [mpegts_init] init first_pcr=22950000 (90khz:76500, ms:850), timestamp mode: copyts=-1
[mpegts @ 0x1591380] [mpegts_init] cbr mode: mux_rate=0 bps, pcr_period=33 ms pat_period=80 ms
[mpegts @ 0x1591380] [mpegts_init] ts->copyts= -1, first_pcr= 22950000, last_pcr=22950000, max_delay= 850000us, period ms: pat=80 sdt=1200 pcr=33, mpegts_flags: hys_mux= 0 no_keyframe_pcr= 0 av_same_mux_delay= 0
Output #0, mpegts, to '/home/ffmpeg-4.4.x/ai_trc_shfiles/nobody_trc/trc_nobody_00001.ts':
Metadata:
encoder : Lavf58.76.100
Stream #0:0: Video: h264, yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 23.98 fps, 90k tbn
Metadata:
encoder : Lavc58.134.100 libx264
Side data:
cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
frame= 1 fps=0.0 q=0.0 size= 0kB time=00:00:00.00 bitrate=N/A speed= 0x
frame= 57 fps= 24 q=0.0 size= 0kB time=00:00:00.00 bitrate=N/A speed= 0x
frame= 69 fps= 24 q=0.0 size= 0kB time=00:00:00.00 bitrate=N/A speed= 0x
frame= 80 fps= 23 q=28.0 size= 256kB time=00:00:00.33 bitrate=6285.0kbits/s speed=0.0979x
frame= 92 fps= 23 q=28.0 size= 512kB time=00:00:00.83 bitrate=5028.1kbits/s speed=0.211x
frame= 103 fps= 23 q=28.0 size= 512kB time=00:00:01.29 bitrate=3243.9kbits/s speed=0.286x
frame= 112 fps= 22 q=28.0 size= 768kB time=00:00:01.66 bitrate=3771.1kbits/s speed=0.331x
frame= 112 fps= 17 q=-1.0 Lsize= 2577kB time=00:00:04.58 bitrate=4601.6kbits/s speed=0.678x
video:2487kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 3.603857%
[libx264 @ 0x15ad340] frame I:3 Avg QP:18.16 size: 59277 PSNR Mean Y:48.36 U:52.91 V:52.56 Avg:49.38 Global:49.30
[libx264 @ 0x15ad340] frame P:51 Avg QP:22.12 size: 32512 PSNR Mean Y:46.27 U:51.56 V:52.01 Avg:47.44 Global:47.08
[libx264 @ 0x15ad340] frame B:58 Avg QP:25.41 size: 12263 PSNR Mean Y:44.93 U:50.65 V:51.14 Avg:46.16 Global:45.98
[libx264 @ 0x15ad340] consecutive B-frames: 7.1% 67.9% 10.7% 14.3% 0.0%
[libx264 @ 0x15ad340] mb I I16..4: 34.1% 59.9% 6.0%
[libx264 @ 0x15ad340] mb P I16..4: 7.8% 24.6% 1.8% P16..4: 22.2% 5.5% 3.0% 0.0% 0.0% skip:35.0%
[libx264 @ 0x15ad340] mb B I16..4: 2.4% 4.9% 0.2% B16..8: 26.3% 3.7% 0.6% direct: 3.2% skip:58.7% L0:47.5% L1:45.0% BI: 7.5%
[libx264 @ 0x15ad340] 8x8 transform intra:69.3% inter:75.8%
[libx264 @ 0x15ad340] direct mvs spatial:81.0% temporal:19.0%
[libx264 @ 0x15ad340] coded y,uvDC,uvAC intra: 42.2% 51.3% 8.0% inter: 11.6% 13.8% 0.1%
[libx264 @ 0x15ad340] i16 v,h,dc,p: 46% 15% 11% 28%
[libx264 @ 0x15ad340] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 38% 13% 14% 4% 6% 8% 6% 7% 5%
[libx264 @ 0x15ad340] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 32% 14% 5% 5% 10% 11% 8% 8% 7%
[libx264 @ 0x15ad340] i8c dc,h,v,p: 44% 18% 31% 8%
[libx264 @ 0x15ad340] Weighted P-Frames: Y:9.8% UV:3.9%
[libx264 @ 0x15ad340] ref P L0: 84.6% 11.6% 2.8% 1.0%
[libx264 @ 0x15ad340] ref B L0: 91.3% 7.2% 1.6%
[libx264 @ 0x15ad340] SSIM Mean Y:0.9919295 (20.931db)
[libx264 @ 0x15ad340] PSNR Mean Y:45.632 U:51.126 V:51.573 Avg:46.828 Global:46.513 kb/s:4362.20
解析上述日志中最后一行,获取PNSR,码率的Python方法如下,供参考
#/****************************************************************************
#* mark_trc.py: mark for x264 encode base on PSNR and bitrate
# python 3.x
#*****************************************************************************
#* Copyright (c) 2021-2022 [email protected]
#* http://blog.csdn.net/zymill
#* http://github.com/zymill
#*****************************************************************************
#* Last update Date: 2021-12-30 19:30:25 version: 0.0.1
#*****************************************************************************
#*/
import os
import re
import sys
import logging
import linecache
from logging import handlers
################################################################################
# 常量参数
trc_target_avg_kbps_sd = 1500 # 720x576
trc_target_avg_kbps_hd = 2000 # 1280x720
trc_target_avg_kbps_uhd = 3000 # 1920x1080
trc_target_avg_kbps_4k = 10000 # 3840x2160
sd_r_list = []
hd_r_list = []
uhd_r_list = []
u4k_r_list = []
score_list = []
################################ 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)
#################################################################################
# check dst_path, create it if not found
def createDirIfNotFound(log, dst_path):
if not os.path.exists(dst_path):
os.makedirs(dst_path)
log.logger.info('created ' + dst_path)
return
log.logger.info('found ' + dst_path)
return
#################################################################################
# parse float value from line
def parseKeyValueFromLine(log, line, pattern):
val = 0.0
result_lst = pattern.findall(line)
log.logger.info(result_lst)
if (len(result_lst) > 0):
val = float(result_lst[0])
return val
#################################################################################
# parse video resolution
# Stream #0:0: Video: h264, yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 23.98 fps, 90k tbn
def parsetVideoResolution(log, line):
global video_width
global video_height
# default value
video_width = 0
video_height = 0
end = line.find("[SAR")
if (end == -1):
return
sub_str = line[0 : end-1]
start = sub_str.rfind(",");
if (start == -1) :
return
sub_str = sub_str[start + 1 : ]
log.logger.info('video resolution str: ' + sub_str)
result_list = sub_str.split('x')
if (len(result_list) == 2):
video_width = int(result_list[0])
video_height = int(result_list[1])
return
#################################################################################
# parse PSNR and bitrate
# [libx264 @ 0x2503340 ] PSNR Mean Y:59.691 U:62.357 V:62.717 Avg:60.439 Global:59.903 kb/s:44056.39
def parsePSNRBitRate(log, line):
global y_psnr
global u_psnr
global v_psnr
global avg_psnr
global global_psnr
global avg_bitrate
# default value
y_psnr = 0.0
u_psnr = 0.0
v_psnr = 0.0
avg_psnr = 0.0
global_psnr = 0.0
avg_bitrate = 0.0
log.logger.debug('psnr_bitrate line: ' + line)
if ((-1 == line.find("PSNR Mean")) or (-1 == line.find("kb/s:"))) :
return
y_psnr = parseKeyValueFromLine(log, line, re.compile(r'(?<=Y:)\d+\.?\d*'))
u_psnr = parseKeyValueFromLine(log, line, re.compile(r'(?<=U:)\d+\.?\d*'))
v_psnr = parseKeyValueFromLine(log, line, re.compile(r'(?<=V:)\d+\.?\d*'))
avg_psnr = parseKeyValueFromLine(log, line, re.compile(r'(?<=Avg:)\d+\.?\d*'))
global_psnr = parseKeyValueFromLine(log, line, re.compile(r'(?<=Global:)\d+\.?\d*'))
avg_bitrate = parseKeyValueFromLine(log, line, re.compile(r'(?<=kb/s:)\d+\.?\d*'))
return
#################################################################################
# [libx264 @ 0x2503340 ] SSIM Mean Y:0.9995006 (33.016db)
def parseSSIM(log, line):
global avg_ssim
avg_ssim = 0
log.logger.info('line: ' + line)
avg_ssim = parseKeyValueFromLine(log, line, re.compile(r'(?<=SSIM Mean Y::)\d+\.?\d*'))
return
#################################################################################
# process one log file
def parseOneLogFile(log, file_name):
if not os.path.exists(file_name):
log.logger.error('file not existed ' + file_name)
return
log.logger.info('start to parse results from file: ' + file_name)
global video_width
global video_height
global y_psnr
global u_psnr
global v_psnr
global avg_psnr
global global_psnr
global avg_bitrate
global avg_ssim
# default value
video_width = 0
video_height = 0
y_psnr = 0.0
u_psnr = 0.0
v_psnr = 0.0
avg_psnr = 0.0
global_psnr = 0.0
avg_bitrate = 0.0
for line_idx, line in enumerate(open(file_name, "rU")):
if ((-1 != line.find("Stream")) and \
(-1 != line.find("Video")) and \
(-1 != line.find("[SAR")) ):
parsetVideoResolution(log, line)
if (-1 != line.find("PSNR Mean") and \
(-1 != line.find("kb/s:"))):
parsePSNRBitRate(log, line)
if (-1 != line.find("SSIM Mean")):
parseSSIM(log, line)
log.logger.info('##########################################################################')
log.logger.info(' video resolution: %d x %d', video_width, video_height)
log.logger.info(' y_psnr : %f', y_psnr)
log.logger.info(' u_psnr : %f', u_psnr)
log.logger.info(' v_psnr : %f', v_psnr)
log.logger.info(' avg_psnr : %f', avg_psnr)
log.logger.info(' global_psnr : %f', global_psnr)
log.logger.info(' avg_bitrate : %f', avg_bitrate)
log.logger.info(' avg_ssim : %f', avg_ssim)
log.logger.info('##########################################################################')
return
################################################################################
# 常量参数
trc_target_avg_kbps_sd = 1500 # 720x576
trc_target_avg_kbps_hd = 2000 # 1280x720
trc_target_avg_kbps_uhd = 3000 # 1920x1080
trc_target_avg_kbps_4k = 10000 # 3840x2160
trc_log_dir_windows = "g:/ai_trc_shfiles/nobody_trc"
trc_log_dir_linux = ""
trc_log_dir = trc_log_dir_windows
# global variables
video_width = 0
video_height = 0
y_psnr = 0.0
u_psnr = 0.0
v_psnr = 0.0
avg_psnr = 0.0
global_psnr = 0.0
avg_bitrate = 0.0
avg_ssim = 0.0 # 暂时未用 ssim 和 psnr 是两种独立的评估方法
#################################################################################
# main process
if __name__ == "__main__":
log = Logger('sys_all.log',level='debug')
Logger('sys_err.log', level='error')
log.logger.info("========= program start ============")
## 获取日志文件列表
root_path = trc_log_dir
# 文件路径列表
file_list = []
log_file_list = []
# 目录路径列表
dir_list = []
traverseDir(root_path, file_list, dir_list)
## show directory info
log.logger.info('>>>')
log.logger.info('found %d dir', len(dir_list))
for dir in dir_list:
log.logger.info(dir)
## filter log file BY ".log"
for file in file_list:
if (-1 != file.rfind(".log")): ## valid transcode log file
log.logger.debug(file)
log_file_list.append(file)
# show log file info
log.logger.info('>>>')
log.logger.info('found %d log files (in %d files)', len(log_file_list), len(file_list))
for file in log_file_list:
## 从日志中解析视频分辨率, PSNR, bitrate等值
parseOneLogFile(log, file)
## end of all cases
log.logger.info("=== end ===")
log.logger.info("============ program exit ============")
sys.exit(0)
################################################################################
# end
#
文章浏览阅读779次,点赞19次,收藏24次。springboot微信小程序的小疾病问诊服务系统的设计与实现。springboot基于spring的物业管理系统的设计与实现。springboot基于Java的高校学生请假系统。ssm基于Android的购物商场APP设计与实现。springboot基于微信小程序的智慧校园系统。ssm基于Android的英语词典的设计与开发。ssm基于SSM+Vue的学生实践管理平台开发。ssm基于android的企业员工考勤系统。ssm基于web的暗香小店系统的设计与实现。ssm基于Web的高等学校公费医疗管理系统。
文章浏览阅读2.3w次,点赞15次,收藏63次。hover属性用不同的书写方式,来改变不同关系的元素样式。元素:hover 表示聚焦后改变自己元素:hover 元素 表示聚焦后改变其子元素元素:hover + 元素 表示聚焦后改变其指定的“亲兄弟”(条件是该兄弟元素与其相邻)元素元素:hover ~ 元素 表示聚焦后改变其指定的兄弟元素,两个元素相不相邻都行。示例:.first:hover {color: white;}/* 聚焦我改变自己 */.three:hover .three-son {font-size: 20px._css hover的用法
文章浏览阅读6k次,点赞3次,收藏15次。coursera-斯坦福-机器学习-吴恩达-第8周笔记-无监督学习coursera-斯坦福-机器学习-吴恩达-第8周笔记-无监督学习1聚类算法clutering1聚类算法简介2K-means21kmeans的目标函数22随机初始化23选择类别数3考试quiz维数约减 dimensionality reduction1数据压缩2数据可视化3维度约简-主成分分析法PCA1 PCA_pca反向压缩
文章浏览阅读5.2k次。一、插件安装Vundle是vim的一个插件管理器, 同时它本身也是vim的一个插件。插件管理器用于方便、快速的安装、删除、Vim更新插件。mkdir -p ~/.vim/bundlegit clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim管理器安装完成后,vim ~/.vimrc命令创建.vimrc文件syntax on" tab宽度和缩进同样设置为4set tabstop=4set softta_bxbx.vim
文章浏览阅读7.2w次,点赞10次,收藏41次。本文适用于当前面临java.lang.ClassNotFoundException挑战的Java初学者。 它将为您提供此常见Java异常的概述,这是一个示例Java程序,可支持您的学习过程和解决策略。 如果您对与更高级的类加载器相关的问题感兴趣,我建议您复习有关java.lang.NoClassDefFoundError的文章系列,因为这些Java异常密切相关。 java.lang..._java.lang.classnotfoundexception:
文章浏览阅读1.2k次,点赞9次,收藏17次。不同的设备间建立连接往往需要通信,而串口通信是十分常用的一种。UART串口通信需要两根线来实现,一根用于串口发送,另外一更用于串口接收。UART串口发送或者接收过程中一帧数据包括1位起始位、8位数据位、1位停止位,为了提高数据的可靠性可以在停止位前加上1位奇偶校验位。串口通信虽然十分简单,但是在不同设备间发送的数据往往不止1个字节,往往需要多个字节组成的数据包。当我们按照数据包发送时我们需要考虑到以及,因此我们可以采用定义数据帧的方式解决上述两个问题。_一帧数据
文章浏览阅读987次,点赞20次,收藏19次。偏微分方程PDE图像去噪(含SNR)完整的代码,方可运行;可提供运行操作视频!适合小白!_pdnet 深度学习 偏微分方程 去噪
文章浏览阅读6.6w次,点赞128次,收藏962次。Ubuntu18.0详尽版安装教程下载Ubuntu18.04下载VMware Workstation安装虚拟机下载Ubuntu18.04官方网站:http://old-releases.ubuntu.com/releases/18.04.4/?_ga=2.44113060.1243545826.1617173008-2055924693.1608557140下载VMware Workstation这个在网上有很多教程下载,这里我就不写了,我用的版本是14 pro。如下图:安装虚拟机1、打开_ubuntu18安装
文章浏览阅读1.7k次。1. 概览Activity的管理有静态和动态两层涵义: 静态是指Activity的代码组织结构,即Application中声明的Activity的集合,这些Activity被组织在一个APK中,有特定的包名。 在编写应用程序时,Activity对应到用户界面,它定义了用户界面的布局、交互行为、启动方式等,最重要的,是Activity的生命周期函数。 在应用进程看来,只需要按照Android定义的规范,实现生命周期函数的具体逻辑即可,所有的用户界面都遵循同一个规范。 编写完一个应用程序的所有用户界面_android activityrecord中的activitytype
文章浏览阅读5.5k次,点赞3次,收藏7次。sed 查找不包含某个特性 sed -i "/src/!s/xxx/bbb/g" xxx将不包含src的行中的xxx替换为bbb_sed不包含字符串
文章浏览阅读6.8k次,点赞11次,收藏18次。问题解决:shared_ptr Assertion px != 0 failed及debug经验分享问题详细描述:/usr/include/boost/smart_ptr/shared_ptr.hpp:646: typename boost::detail::sp_dereference::type boost::shared_ptr::operator*() const [with T = pcl::PointCloudpcl::pointxyz; typename boost::detail::sp_typename boost::detail::sp_dereference::type boost::shared_ptr::operat
文章浏览阅读553次。编者按:在这个万物智联的时代,无论是在线网络购物,还是网络强国、数字中国建设,都离不开一张“看不见的网”——基础设施网络。2009年,首届双11每秒交易订单创建峰值400;2021年,双11每秒交易订单创建峰值58.3万,12年交易数字量猛增的背后,是阿里云在庞大分布式系统上计算和IO能力的飞跃,更离不开阿里云基础设施底层网络技术的支撑。图|阿里云全球基础设施网络系统作为阿里云基础设施的重要组成部分,阿里云基础设施网络团队负责整个阿里云全球基础设施网络,包括大规模高性能数据中心网络,全球数据中心互联_阿里云网络基线理解