首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提取由编解码器生成的视频的所有图片组(GOPs)。

问提取由编解码器生成的视频的所有图片组(GOPs)。
EN

Stack Overflow用户
提问于 2022-07-21 10:56:18
回答 1查看 86关注 0票数 2

我正在对一个视频做一些重构技术,而不是立即在整个视频上使用这些技术,我想分别在视频的图片组(GOPs)上使用这些技术,所以我想知道的是,有什么方法可以提取由编解码器生成的视频的图片组。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-21 21:26:30

图片组(GOP)应用从关键帧开始的所有视频帧,并在下一个关键帧之前结束一个帧。

(上述定义假定为"关闭共和党人")。

以下职位有将视频分割成GOP的示例,但是没有Python代码示例,我不确定这个剧本是否真的工作。

对于将视频文件分割成多个文件时,每个文件是一个GOP,我们可以使用段穆克塞与-segment_times参数。

-segment_times需要一个时间戳列表。我们shell提供输入文件中所有关键帧的时间戳列表。

让我们首先构建一个用于测试的输入视频文件(使用FFmpeg CLI):

ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1:duration=100 -vcodec libx264 -g 10 in.mp4

上面的命令构建一个固定GOP大小为10帧的合成视频文件(用于测试)。

框架是有编号的,所以很容易跟踪.

使用FFprobe CLI获取所有关键帧的时间戳(用于演示概念):

ffprobe -skip_frame nokey -select_streams v:0 -show_frames -show_entries frame=pkt_pts_time -of json in.mp4 > tmp.txt

(将从Python执行类似的命令)。

上面的命令以JSON格式创建一个带有所有关键帧时间戳的文本文件:

代码语言:javascript
复制
{
    "frames": [
    ...    
    {
        "pkt_pts_time": "10.000000"
    },
    {
        "pkt_pts_time": "20.000000"
    },
    ...
}

segment_times列表将是:"10.000000,20.000000,30.000000..."。

使用Python脚本以编程方式将视频文件拆分为GOP:

  • 使用FFprobe获取所有关键帧的PTS时间戳(以JSON格式获取): data =sp.run(‘ff探针’,'-skip_frame','nokey','-select_streams','v:0',‘-show_frame’,'-show_entries','frame=pkt_pts_time','-of','json',in_file_name,stdout=sp.PIPE).stdout
  • 将JSON (string)转换为字典,并从字典中获取“frames”: dict =json.loads(数据) frames_dict =dict‘’frames‘
  • 构建以逗号分隔的时间戳字符串: pts_list =frames_dict中项目的项目‘’pkt_pts_time‘segment_times = ",".join(pts_list)
  • 使用FFmpeg将输入视频拆分为时间戳(文件:out0000.mp4、out0001.mp4、out0002.mp4): sp.run('ffmpeg','-i',in_file_name,'-codec','copy','-f',‘段’,‘-重置_时间戳’,'1',‘-段_time’,segment_times,'out%04d.mp4')

上面的代码使用子流程模块在Python中执行FFmpeg和FFprobe。

确保ffmpeg和ff探头处于退出路径。

Python代码:

代码语言:javascript
复制
import subprocess as sp
import json

# Preparation: build synthetic video file for testing
# ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1:duration=100 -vcodec libx264 -g 10 in.mp4

in_file_name = 'in.mp4'  # Input file name

# Use FFprobe for getting the PTS timestamps of all key frames (get it in JSON format).
data = sp.run(['ffprobe', '-skip_frame', 'nokey', '-select_streams', 'v:0', '-show_frames', '-show_entries', 'frame=pkt_pts_time', '-of', 'json', in_file_name], stdout=sp.PIPE).stdout
dict = json.loads(data)  # Convert from JSON (string) to dictionary 
frames_dict = dict['frames']  # Get 'frames' out of the dictionary

pts_list = [item['pkt_pts_time'] for item in frames_dict]  # Convert to list: ['0.000000', '10.000000', '20.000000', ...]
segment_times = ",".join(pts_list)  # Convert list to comma separated string: '0.000000,10.000000,20.000000,...'

# Use FFmpeg for splitting the input video by timestamps (files: out0000.mp4, out0001.mp4, out0002.mp4)
# Each segment file is going to be a GOP - start from key-frame, and end one frame before the next key-frame.
sp.run(['ffmpeg', '-i', in_file_name, '-codec', 'copy', '-f', 'segment', '-reset_timestamps', '1', '-segment_times', segment_times, 'out%04d.mp4'])

注意:

  • 以上解决方案可能不适用于所有编解码器和所有文件格式。 例如,H.265编解码器存在分割问题(由于FFmpeg限制)。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73064958

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档