当前位置: 首页 > news >正文

视频调整帧率、分辨率+音画同步

# python data_utils/pre_video/multi_fps_crop_sync.pyimport cv2
import os
from tqdm import tqdm
import subprocess# 加载人脸检测模型
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')def contains_face(frame):gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = face_cascade.detectMultiScale(gray, 1.3, 5)return len(faces) > 0def crop_center(frame, crop_width, crop_height):height, width = frame.shape[:2]start_x = width//2 - crop_width//2start_y = height//2 - crop_height//2return frame[start_y:start_y+crop_height, start_x:start_x+crop_width]def extract_audio(input_path, audio_path):subprocess.run(['ffmpeg', '-y', '-i', input_path, '-vn', '-acodec', 'copy', audio_path])def merge_video_audio(video_path, audio_path, output_path):# 使用ametadata滤镜将音频的时间戳与视频流的时间戳对齐subprocess.run(['ffmpeg', '-y', '-i', video_path, '-i', audio_path,'-filter_complex', "[0:v][0:a]ametadata=mode=video:video_input=0:video_stream=0[a]",'-map', '0:v', '-map', '[a]','-c:v', 'copy', '-c:a', 'aac',output_path])def process_video(path, out_path, fps=25):print(f'[INFO] ===== process video from {path} to {out_path} =====')# 创建VideoCapture对象cap = cv2.VideoCapture(path)# 检查是否成功打开视频if not cap.isOpened():print("Error opening video file")returnframe_rate = cap.get(cv2.CAP_PROP_FPS)total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 获取视频的总帧数frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # 获取视频的宽度frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 获取视频的高度print("原视频帧率=", frame_rate, "fps")print("原视频帧数=", total_frames)print("原视频尺寸=", frame_width, "x", frame_height)if frame_rate != fps:cap.set(cv2.CAP_PROP_FPS, fps)frame_rate = fps# 创建VideoWriter对象fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter(out_path, fourcc, fps, (512, 512))frame_count = 0# 创建一个tqdm进度条pbar = tqdm(total=total_frames, ncols=70, unit='frame')while cap.isOpened():ret, frame = cap.read()if ret:if contains_face(frame) and frame_count % (frame_rate // fps) == 0:frame = crop_center(frame, 512, 512)out.write(frame)frame_count += 1pbar.update(1)  # 更新进度条else:breakpbar.close()  # 关闭进度条cap.release()out.release()print(f'[INFO] ===== processed video =====')# 打开处理后的视频,获取总帧数、帧率和视频尺寸cap_out = cv2.VideoCapture(out_path)total_frames_out = int(cap_out.get(cv2.CAP_PROP_FRAME_COUNT))frame_rate_out = cap_out.get(cv2.CAP_PROP_FPS)frame_width = int(cap_out.get(cv2.CAP_PROP_FRAME_WIDTH))frame_height = int(cap_out.get(cv2.CAP_PROP_FRAME_HEIGHT))print(f'处理后的视频帧率: {frame_rate_out} fps')print(f'处理后的视频帧数: {total_frames_out}')print(f'处理后的视频尺寸: {frame_width}x{frame_height}')cap_out.release()def process_video_with_audio(input_path, output_path):audio_path = output_path.replace('.mp4', '_audio.aac')output_with_audio_path = output_path.replace('.mp4', '_with_audio.mp4')# 分离音频extract_audio(input_path, audio_path)# 处理视频process_video(input_path, output_path)# 重新同步并合并音频和视频merge_video_audio(output_path, audio_path, output_with_audio_path)# 删除临时文件os.remove(output_path)os.remove(audio_path)return output_with_audio_pathif __name__ == "__main__":for i in tqdm(range(1, 75), desc="Processing videos"):input_path = f"data/{i}/{i}.mp4"output_path = f"data/{i}/{i}_fc.mp4"if not os.path.isfile(input_path):print(f"文件 {input_path} 不存在.")continuefinal_output_path = process_video_with_audio(input_path, output_path)print(f"处理后的视频已保存至 {final_output_path}")

对于音视频不同步的问题,尤其是在使用ffmpegadelay滤镜时,如果只是简单地调整延迟,可能会因为视频和音频流的时间戳没有精确对齐而导致最终输出的视频中音画不同步。为了更精确地实现音视频同步,我们可以采取以下步骤:

  1. 提取视频流的时间戳:从原始视频中提取视频流的时间戳,这样我们就可以知道每个视频帧应该在什么时间点出现。

  2. 提取音频流的时间戳:同样地,从原始音频中提取音频流的时间戳,了解音频数据包的时间位置。

  3. 调整音频流的时间戳:根据需要提前或延后的时间,调整音频流的时间戳,使得它与视频流的时间戳对齐。

  4. 使用ffmpeg重新封装:将调整过时间戳的音频流与视频流重新封装在一起,确保时间戳的对齐。

然而,直接在Python中操作音视频流的时间戳可能比较复杂,通常推荐的方式是在ffmpeg中使用[0:v][0:a]ametadata=mode=video:video_input=0:video_stream=0[a]这样的滤镜链,来确保音频流的时间戳与视频流的时间戳对齐。

以下是修改后的merge_video_audio函数,使用ffmpegametadata滤镜来尝试更好地同步音视频:

def merge_video_audio(video_path, audio_path, output_path):# 使用ametadata滤镜将音频的时间戳与视频流的时间戳对齐subprocess.run(['ffmpeg', '-y', '-i', video_path, '-i', audio_path,'-filter_complex', "[0:v][0:a]ametadata=mode=video:video_input=0:video_stream=0[a]",'-map', '0:v', '-map', '[a]','-c:v', 'copy', '-c:a', 'aac',output_path])

但请注意,ametadata滤镜并不总是能完美解决所有不同步问题,特别是当音频和视频的编码器或解码器有时间基(timebase)差异时。在这种情况下,你可能需要更深入地理解ffmpeg的时间基概念以及如何正确地设置它们,或者使用更复杂的滤镜链来确保时间戳的一致性。

另外,上述代码中并没有直接处理时间戳的调整,而是依赖于ffmpeg的滤镜来试图自动对齐音视频的时间戳。如果视频和音频流的时间基不同,或者存在其他复杂的时间偏移,你可能需要手动计算和调整时间戳,这通常涉及到更复杂的ffmpeg命令行技巧或使用专门的音视频处理库。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 丑数问题,力扣264,坑点
  • markdown文件转pdf
  • 了解AsyncRotationController
  • 【C语言】C语言-身份证管理系统(源码+注释)【独一无二】
  • mybatis日志记录方案
  • 解决vue多层弹框时存在遮挡问题
  • 新质生产力赛道核心解读,机械制造何以“向智向新”
  • 深入理解Spring Cloud中的服务注册
  • Docker Desktop如何换镜像源?
  • jdevelope安装
  • MinIO:开源对象存储解决方案的领先者
  • FlyDeliver践行社会责任,推动绿色物流发展
  • vue前端面试
  • 数据建设实践之大数据平台(四)
  • 搜索引擎算法工程师,在query理解方面,都有哪些方面的工作
  • python3.6+scrapy+mysql 爬虫实战
  • 10个最佳ES6特性 ES7与ES8的特性
  • Apache Spark Streaming 使用实例
  • docker容器内的网络抓包
  • ES10 特性的完整指南
  • HTML中设置input等文本框为不可操作
  • java 多线程基础, 我觉得还是有必要看看的
  • magento 货币换算
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • 闭包,sync使用细节
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 使用parted解决大于2T的磁盘分区
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 学习Vue.js的五个小例子
  • ‌移动管家手机智能控制汽车系统
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #java学习笔记(面向对象)----(未完结)
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (4)STL算法之比较
  • (zt)最盛行的警世狂言(爆笑)
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (九)c52学习之旅-定时器
  • (力扣题库)跳跃游戏II(c++)
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (七)理解angular中的module和injector,即依赖注入
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (转)mysql使用Navicat 导出和导入数据库
  • **python多态
  • .bashrc在哪里,alias妙用
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .NET gRPC 和RESTful简单对比
  • .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...
  • .NET/C# 使用反射调用含 ref 或 out 参数的方法