今天运用所学的知识来尝试解决一下工作中的问题(我的工作是做视频相关的)

首先,我想要通过代码检查一个视频文件的质量,例如有没有丢帧,如果有丢帧的情况,会造成播放视频会卡顿

搜了一些资料,要判断一个视频文件是否丢帧,可借助Python的OpenCV库来实现

第一步是安装OpenCV库,在这一步遇到了挺多困难浪费了很多时间,在此不再对遇到的问题做具体列举,只写一下能成功的方法

第一步:确保正确安装了环境变量

在cmd命令行发送指令python --version,若能正确返回python的版本,则证明环境变量是配置正常的

若未返回python版本,则需要配置一下环境变量

可以在电脑上直接搜环境变量

点击环境变量

在系统变量这里找到Path

添加 Python 安装目录(例如C:\Python39)和 Python 安装目录下的Scripts文件夹路径(例如C:\Python39\Scripts

保存配置后,在cmd命令行发送指令python --version,若能正确返回python的版本,则证明环境变量配置成功

第二步:在命令行中安装opencv-python库

在cmd中发送指令pip install opencv-python即可成功安装

到此,前期准备结束,接下来是代码部分

1. 打开视频文件:使用cv2.VideoCapture打开视频文件。

2. 逐帧读取视频:使用cap.read()逐帧读取视频,并通过cap.get(cv2.CAP_PROP_POS_FRAMES)获取当前帧的序号。

3. 检查帧序号的连续性:比较当前帧的序号和前一帧的序号,如果不连续,则认为存在丢帧现象。

import cv2


def check_frame_loss(video_path):
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        print("无法打开视频文件")
        return

    # 获取视频的帧率和总帧数
    fps = cap.get(cv2.CAP_PROP_FPS)
    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

    # 计算理论时长(秒)
    theoretical_duration = frame_count / fps

    # 实际读取视频帧并计时
    actual_frame_count = 0
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        actual_frame_count += 1

    # 释放资源
    cap.release()

    # 计算实际时长(秒)
    actual_duration = actual_frame_count / fps

    # 判断是否丢帧
    if abs(actual_duration - theoretical_duration) > 0.1:
        print("视频可能存在丢帧现象")
    else:
        print("视频未发现丢帧现象")


if __name__ == "__main__":
    video_file = 'C:\\Users\\zt\\Desktop\\CH1_20250312_133207_000000.ts'
    check_frame_loss(video_file)

找了一个有丢帧的录像文件,运行后的结果如下

能正确检测中视频中的丢帧情况

改一下需求:

1. 检测某个文件夹内所有视频文件是否有丢帧

2. 打印每个文件夹是否有丢帧,总共丢了多少帧

代码如下:

import cv2
import os


def check_frame_loss(video_path):
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        print(f"无法打开视频文件: {video_path}")
        return 0

    # 获取视频的帧率和总帧数
    fps = cap.get(cv2.CAP_PROP_FPS)
    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

    # 计算理论时长(秒)
    theoretical_duration = frame_count / fps

    # 实际读取视频帧并计时
    actual_frame_count = 0
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        actual_frame_count += 1

    # 释放资源
    cap.release()

    # 计算实际时长(秒)
    actual_duration = actual_frame_count / fps

    # 计算丢帧数量
    lost_frames = int(abs(frame_count - actual_frame_count))

    return lost_frames


def check_all_videos_in_folder(folder_path):
    total_lost_frames = 0
    for root, dirs, files in os.walk(folder_path):
        for file in files:
            if file.lower().endswith(('.mp4', '.avi', '.mov', '.ts')):
                video_path = os.path.join(root, file)
                lost_frames = check_frame_loss(video_path)
                total_lost_frames += lost_frames
                if lost_frames > 0:
                    print(f"视频 {video_path} 存在丢帧,丢帧数量: {lost_frames}")
                else:
                    print(f"视频 {video_path} 未发现丢帧")

    print(f"文件夹内所有视频总共丢帧数量: {total_lost_frames}")


if __name__ == "__main__":
    folder = 'C:\\Users\\zt\\Desktop\\record'
    check_all_videos_in_folder(folder)

运行后:

补充一下了解到的获取当前帧序号的原理:

视频文件的底层结构

视频文件通常由一系列的帧(图像)组成,这些帧按照一定的时间顺序排列,形成连续的动态画面。视频文件格式(如 MP4、AVI、TS 等)会定义如何存储这些帧以及相关的元数据。元数据包含了视频的基本信息,例如帧率、分辨率、时长等,还可能记录了每帧在文件中的位置信息。

OpenCV 对视频流的管理

OpenCV 使用cv2.VideoCapture类来读取视频文件。当你创建一个cv2.VideoCapture对象并打开视频文件时,OpenCV 会解析视频文件的元数据,建立一个视频流的读取指针。这个指针指向视频文件中的当前位置,随着视频帧的读取,指针会逐帧向后移动。

获取当前帧序号的方法

在 OpenCV 中,你可以使用cap.get(cv2.CAP_PROP_POS_FRAMES)方法来获取当前帧的序号,其原理如下:

初始化:当你调用cv2.VideoCapture打开视频文件时,读取指针初始指向视频的第一帧,此时cap.get(cv2.CAP_PROP_POS_FRAMES)返回值为 0。

逐帧读取:每次调用cap.read()方法读取一帧时,OpenCV 会将读取指针向后移动到下一帧的位置,并更新cv2.CAP_PROP_POS_FRAMES的值。因此,在读取每帧后调用cap.get(cv2.CAP_PROP_POS_FRAMES),就可以得到当前帧在视频中的序号。

序号连续性:正常情况下,视频帧的序号是连续递增的。例如,第一帧序号为 0,第二帧序号为 1,以此类推。如果在读取过程中发现序号不连续,可能意味着视频存在丢帧现象。

今天主要了解了一下如何实现检查一个视频是否有丢帧情况,后续的学习主要围绕工作相关的,如何通过代码提高效率的方法,欢迎大家监督~

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐