PyAV源码安装及基本使用

PyAV源码编译

PyAV是对 ffmpeg 库的 Python 绑定,本篇介绍PyAV的源码安装及基本使用。

文章目录

  • PyAV源码编译
    • 编译流程
    • 源码目录结构
    • 编译中遇到的问题
  • PyAV的使用
    • nvidia 硬件编解码
    • Python C++ debug 方式

编译流程

PyAV的源码地址为:https://github.com/PyAV-Org/PyAV 根据README进行安装即可。

  1. source scripts/activate.sh
    启动虚拟环境,需要安装python模块-virtualenv,使用的python版本是默认路劲下的python版本,/usr/bin/python 或者miniconda3/bin/python;在scripts/activate.sh中,通过变量PYAV_PYTHON可以指定虚拟环境所使用的python版本:
export PYAV_PYTHON=~/miniconda3/envs/py310/bin/python
source scripts/activate.sh
  1. pip install --upgrade -r tests/requirements.txt
    requirements.txt 里指定所需模块,但是没有指定版本,默认为最新版本。
  2. ./scripts/build-deps
    这里会在目录PyAV/vendor下 编译ffmpeg, 如何存在ffmpeg则跳过ffmpeg的编译,可以在这里替换自己的ffmpeg 。
  3. make
  4. pip install .

源码目录结构

PyAV/

├── av/ # PyAV 的核心模块,可以查看对应的Python接口是怎么调用到ffmpeg接口的
├── docs/ # 文档目录
├── src/ # Cython 代码,将代码翻译成 C 代码并编译成扩展模块,以提供 Python 与 C/C++ 之间的接口
├── examples/ # 示例代码目录
├── tests/ # 测试代码目录 外部通过import test.xxx 进行使用
├── vendor #ffmpeg 安装路劲
├── venvs #虚拟环境安装路径
├── CHANGELOG.rst # 变更日志 可以看到各个版本支持的ffmpeg 和 python版本
├── setup.cfg # setuptools 配置文件
└── setup.py # 安装脚本

编译中遇到的问题

直接编译最新版本应该问题不大,但是为了适配我的ffmpeg版本(ffmpeg-4.2),我对PyAV的版本进行了回退:

PyAV历史产出包:PyAV-tags

make时报log_callback的错误:

performance hint: av\logging.pyx:232:5: Exception check on ‘log_callback’ will always require the GIL to be acquired.
Possible solutions:
1. Declare the function as ‘noexcept’ if you control the definition and you’re sure you don’t want the function to raise exceptions.
2. Use an ‘int’ return type on the function to allow an error code to be returned.
Error compiling Cython file:
------------------------------------------------------------

cdef const char *log_context_name(void *ptr) nogil:
cdef log_context obj = <log_context>ptr
return obj.name
cdef lib.AVClass log_class
log_class.item_name = log_context_name

通过查阅资料,大致的解决办法都是回退python的版本: Python 3.13.x -> python 3.12.x ,如下面这篇问题:
https://stackoverflow.com/questions/77410272/problems-installing-python-av-in-windows-11
但是我在PyAV-8.1.0中回退版本无效,后来通过回退Cython的版本解决的,默认安装的Cython版本为3.x, 这里我回退到0.29.24。
另外还有下面这个报错,我是通过回退python版本解决的:

fatal error: longintrepr.h: 没有那个文件或目录

总结起来就是版本需要对应上,这里尝试了两种版本可以编译通过:

PythonCythonPyAVffmpeg
3.100.29.248.1.04.2
3.113.0.911.06.0

PyAV的使用

仓库里在目录example下提供了许多case,很值得参考;另外,关于video解码可以参考这篇:
https://blog.csdn.net/weixin_43360707/article/details/131654650

nvidia 硬件编解码

下面是使用nvidia的硬件解码器,解码mp4文件的case, 前提是ffmpeg需要编译出h264_cuvid和h264_nvenc编解码器。
nvidia 解码,将裸流解码为yuv文件

import os
import subprocessimport av
import av.datasets# We want an H.264 stream in the Annex B byte-stream format.
# We haven't exposed bitstream filters yet, so we're gonna use the `ffmpeg` CLI.
h264_path = 'night-sky.h264'fh = open(h264_path, 'rb')codec = av.CodecContext.create('h264_cuvid', 'r')
output_file = "output.yuv"
output = open(output_file, 'wb')
while True:chunk = fh.read(1 << 16)packets = codec.parse(chunk)print("Parsed {} packets from {} bytes:".format(len(packets), len(chunk)))for packet in packets:print('   ', packet)frames = codec.decode(packet)for frame in frames:print('       ', frame)# yuv_frame = frame.to_ndarray(format='yuv420p')# output.write(yuv_frame.tobytes())yuv_frame = frame.reformat(1920, 1080, 'yuv420p')output.write(yuv_frame.planes[0].to_bytes())output.write(yuv_frame.planes[1].to_bytes())output.write(yuv_frame.planes[2].to_bytes())# We wait until the end to bail so that the last empty `buf` flushes# the parser.if not chunk:break
output.close()

通过 watch -n 1 nvidia-smi 可以检查是否正真的调用到nvidia的硬件。
nvidia 编码,将yuv文件编码为码流文件

import av
import numpy as npinput_file = "input.yuv"output_raw_file = "stream.h264"
output_media_file = "output.mp4"#org yuv resolutions
width = 1920
height = 1080input_yuv = open(input_file, 'rb')
output = open(output_raw_file, 'wb')output_container = av.open(output_media_file, 'w')
output_stream = output_container.add_stream('h264_nvenc')#strat encode
frame_count = 0
while True:y_data = input_yuv.read(width * height)u_data = input_yuv.read(width * height // 4)v_data = input_yuv.read(width * height // 4)if not y_data or not u_data or not v_data:break#create AVframe for encodingyuv = np.concatenate([np.frombuffer(y_data, dtype=np.uint8),np.frombuffer(u_data, dtype=np.uint8),np.frombuffer(v_data, dtype=np.uint8)])yuv = yuv.reshape((height * 3 // 2, width))frame = av.VideoFrame.from_ndarray(yuv, format='yuv420p')#encodefor packet in output_stream.encode(frame):# output raw streamoutput.write(packet.to_bytes())#or: mux to mp4 media-format# output_container.mux(packet)frame_count += 1input_yuv.close()
output.close()
print(f"Encoded {frame_count} frames.")

nvidia 转码,将H264-mp4转为HEVC-mp4

import avinput_file = 'H264_1080P.mp4'
output_file = 'HEVC_1080P.mp4'input_container = av.open(input_file)# video_stream = next(s for s in input_container.streams if s.type == 'video')
video_stream = input_container.streams.video[0]
output_container = av.open(output_file, 'w')output_stream = output_container.add_stream('hevc_nvenc', rate=video_stream.rate) #enccodec = av.CodecContext.create('h264_cuvid', 'r') #dec#copy avcodec_ctx->extradata & avcodec_ctx->extradata_size
codec.extradata = video_stream.extradata#output yuv if you want
output_file = "output.yuv"
output = open(output_file, 'wb')# transcode
for packets in input_container.demux(video_stream):print(packets)frames = codec.decode(packets)for frame in frames:# mux to mp4for packet in output_stream.encode(frame):output_container.mux(packet)#yuv_frame = frame.to_ndarray(format='yuv420p')output.write(yuv_frame.tobytes())input_container.close()
output_container.close()
output.close()

在我的测试中,需要在解码之前加上codec.extradata = video_stream.extradata这句语句,否则codec.decode(packet)返回的frame list为空,不清楚是不是算是一个bug。具体来说在ffmpeg的demux demo(doc/examples/demuxing_decoding.c)中,使用函数avcodec_parameters_to_context进行参数的拷贝,而PyAV可能缺少了这一步骤。

Python C++ debug 方式

由于PyAV对ffmpeg进行了python封装,直接使用gdb抓不到Python程序,使用pdb又进不了C函数;因此需要一种Python C++的debug方案。
在VScode中有Python C++ debugger 插件,里面介绍了用法,可以一试;还有其他的VScode调试方法如:
https://nadiah.org/2020/03/01/example-debug-mixed-python-c-in-visual-studio-code/

下面这篇文章提到了Python C++的debug 方式,指出:“调试器的工作机制都是将执行代码中的代码替换成一个异常处理的代码,让程序的执行跳转到调试器中的处理流程去”,也就是直接用gdb去attach python的进程就能对C的代码流程进行调试:
编译、调试PyTorch源码1

实际使用中,我用pdb + gdb 的方法常常会卡死,可能是机器的问题
终端1:pdb + print(os.getpid()) + pdb.set_trace()
终端2:gdb -p < pid >
怀疑是pdb和gdb的冲突,所以后来我在python中进行延迟(time.sleep(10)),为了是在启动gdb之前获取当前Python进程的pid,然后再用gdb去attach pid,通过break打点,代码运行到断点出可以查看栈信息

欢迎评论、讨论以及指出错误, Thanks ~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/768215.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

政安晨:【深度学习实践】【使用 TensorFlow 和 Keras 为结构化数据构建和训练神经网络】(五)—— Dropout和批归一化

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; Dropout和批归一化是深度学习领域中常用的正则化技术…

stm32之GPIO寄存器

文章目录 1 背景2 GPIO寄存器的类型2.1 端口配置寄存器2.2 设置/清除寄存器和位清除寄存器 3 总结 1 背景 C51单片机在进行数据的输入输出时&#xff0c;是直接操作与外部引脚关联的内部寄存器&#xff0c;例如&#xff0c;当设置P2_1为0时&#xff0c;就是将外部引脚的P21引脚…

YOLOV5 部署:TensorRT的安装和使用

1、介绍 TensorRT 可以加速神经网络的推理时间,常常在工业生产中使用 因为TensorRT需要使用到cuda和cudnn加速,所以需要安装这两个,安装的具体步骤参考前文: YOLOV5 部署:cuda和cuDNN安装-CSDN博客 2、TensorRT 下载 TensorRT下载地址:NVIDIA TensorRT Download | NV…

6.windows ubuntu 子系统 测序数据质量控制。

上一个分享&#xff0c;我们对测序数据进行了质量评估&#xff0c;接下来我们需要对数据进行数据质量控制。 数据预处理&#xff08;Data Preprocessing&#xff09;&#xff1a;包括去除接头序列&#xff08;adapter trimming&#xff09;、去除低质量序列&#xff08;qualit…

Spark—GraphX实战 OneID

OneID 前面我们学习了ID Mapping&#xff0c;包括ID Mapping 的背景介绍和业务场景&#xff0c;以及如何使用Spark 实现ID Mapping&#xff0c;这个过程中涉及到了很多东西&#xff0c;当然我们都通过文章的形式介绍给大家了&#xff0c;所以你再学习今天这一节之前&#xff0…

FPGA时钟资源详解——时钟Buffer的选择

目录 一、概述 二、时钟Buffer的选择 2.1 BUFG 2.2 BUFR 和 BUFIO 2.2.1 源同步接口的支持 2.2.2 扩展时钟域转换功能 2.2.3 BUFR 作为简单的时钟分频器 2.3 BUFH 2.3.1 BUFH 的关键特性 2.3.2 应用场景 三、总结 3.1 BUFG&#xff08;全局时钟缓冲器&…

OpenCV4.9.0开源计算机视觉库核心功能(核心模块)

转到&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV 介绍使用 下一篇&#xff1a;如何使用OpenCV扫描图像、查找表和时间测量 ​ OpenCV核心功能主要有以下各个&#xff1a;本文将开始介绍下列内容&#xff1a; Mat - 基…

SpringBoot配置JWT拦截器

目录 1.背景介绍 2.前提工作 3.具体代码 &#xff08;1&#xff09;相关依赖 &#xff08;2&#xff09;相关配置文件 &#xff08;3&#xff09;JwtUtils类 &#xff08;4&#xff09;准备好登录逻辑代码&#xff08;Dao、Service、Controller&#xff09; &#xff0…

解决方案Please use Oracle(R) Java(TM) 11, OpenJDK(TM) 11 to run Neo4j.

文章目录 一、现象二、解决方案 一、现象 当安装好JDK跟neo4j&#xff0c;用neo4j.bat console来启动neo4却报错&#xff1a; 部分报错信息&#xff1a; Starting Neo4j. WARNING! You are using an unsupported Java runtime. Please use Oracle Java™ 11, OpenJDK™ 11 t…

大白话扩散模型(无公式版)

背景 传统的图像生成模型有GAN&#xff0c;VAE等&#xff0c;但是存在模式坍缩&#xff0c;即生成图片缺乏多样性&#xff0c;这是因为模型本身结构导致的。而扩散模型拥有训练稳定&#xff0c;保持图像多样性等特点&#xff0c;逐渐成为现在AIGC领域的主流。 扩散模型 正如…

设计模式学习笔记 - 设计模式与范式 - 创建型:6.建造者模式:详解构造函数、set方法、建造者三种对象创建方式

概述 本章学习一个比较常用的创建型设计模式&#xff0c;Builder 模式&#xff0c;中文翻译为建造者模式或构建者模式&#xff0c;也有人叫它生成器模式。 建造者模式的原理和代码实现非常简单&#xff0c;掌握起来并不难&#xff0c;难点在于应用场景。比如&#xff0c;你有…

Google ScreenAI代表了一款先进的视觉语言模型,专为用户界面(UI)和视觉情境下的语言理解而设计

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

华为od真题2023-C卷-三叉搜索树

题目描述&#xff1a; 定义构造三叉搜索树规则如下: 每个节点都存有一个数&#xff0c;当插入一个新的数时&#xff0c;从根节点向下寻找&#xff0c;直到找到一个合适的空节点插入。查找的规则是: 1.如果数小于节点的数减去500&#xff0c;则将数插入节点的左子树2.如果数大于…

政安晨:【深度学习部署】—— TensorFlow Extended(TFX)介绍

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎机器学习 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 前言 TensorFlow Extended&#xff08;TFX&a…

深入了解Redis的过期策略和内存淘汰机制

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起进步&am…

语言模型的原理、实战与评估

语言模型的原理、实战与评估是一个宽泛的话题,下面是对这三个方面简要概述: 语言模型的原理 语言模型(Language Model, LM)是一种统计模型,用于估计一段文本序列的概率分布。它的核心任务是给定一系列词语,计算出这些词语组合成一个完整句子或段落的概率。典型的语言模型…

mysql基础2多表查询

多表查询 多表关系: 一对多 案例: 部门 与 员工的关系 关系: 一个部门对应多个员工&#xff0c;一个员工对应一个部门 实现: 在多的一方建立外键&#xff0c;指向一的一方的主键 多对多 案例: 学生 与 课程的关系 关系: 一个学生可以选修多门课程&#xff0c;一门课程也可以…

MySQL基础复习

目录 一、简单的命令 二、SQL语句分类 三、简单查询 四、条件查询 五、排序 一、简单的命令 net start 服务名称 net stop 服务名称 mysql -uroot -p123456 显示密码形式 mysql -uroot -p 隐藏密码形式 exit 退出 show databases; 查看MySQL中的数据库有哪些 use test…

RuleApp资源社区,知识付费社区,可对接typecho的小程序APP

强大的文章/社区/自媒体客户端&#xff0c;支持打包为安卓&#xff0c;苹果&#xff0c;小程序。包括文章模块&#xff0c;用户模块&#xff0c;支付模块&#xff0c;聊天模块&#xff0c;商城模块等基础功能&#xff0c;包含VIP会员&#xff0c;付费阅读等收费体系&#xff0c…

AttributeError: ‘_MSDataLoaderIter‘ object has no attribute ‘_put_indices‘

问题描述 复现代码过程中遇到错误&#xff1a;AttributeError: _MSDataLoaderIter object has no attribute _put_indices 解决方案 出错的原因是代码中使用了不存在的属性"_put_indices"。这个错误可能与你使用的版本不兼容有关。在pytorch1.x版本中&#xff0c;&q…