基于YOLOv8的自动剪辑视频脚本:提取并合并有人片段

1. 项目背景

在视频素材的搜集过程中,尤其是针对人的动作素材,我们常需要从大量包含无人画面的视频中筛选出有人出现的片段。手动进行这一筛选过程不仅耗时,而且容易遗漏关键片段。为了提高效率,我写了一个基于YOLOv8的自动裁剪视频脚本,能够自动检测视频中是否存在人物,并提取出包含人物的片段,最后将这些片段拼接在一起,以便进一步筛选和使用。

2. 环境配置

2.1 安装YOLOv8环境

首先,确保已经安装了能够正常运行YOLOv8的环境。YOLOv8通常需要Python 3.7或更高版本,并且依赖于一些常见的Python库,如ultralyticsopencv-python等。可以通过以下命令安装这些依赖库:

pip install ultralytics opencv-python

2.2 安装FFmpeg

FFmpeg是一个强大的多媒体处理工具,支持视频和音频的编解码、转码、剪辑等操作。我们需要安装FFmpeg以便在Python脚本中使用。

2.2.1 使用conda安装FFmpeg(适用于Windows和macOS)

如果你使用的是Anaconda或Miniconda,可以通过以下命令从conda-forge渠道安装FFmpeg:

conda install -c conda-forge ffmpeg

2.2.2 使用apt安装FFmpeg(适用于Linux)

如果你使用的是Linux系统,可以通过以下命令安装FFmpeg:

sudo apt install ffmpeg

2.2.3 验证FFmpeg安装

安装完成后,可以通过以下命令验证FFmpeg是否安装成功:

ffmpeg -version

如果输出了版本信息,则说明FFmpeg已经成功安装并且配置正确。

2.3 安装ffmpeg-python库和tqdm库

ffmpeg-python是一个Python库,提供了对FFmpeg命令的封装,使得我们可以在Python脚本中方便地调用FFmpeg。而tqdm 是一个快速、可扩展的 Python 进度条库,可以在长循环中添加一个进度提示信息,为长时间的循环操作提供视觉反馈。

pip install ffmpeg-python
pip install tqdm

3. 代码实现(两种方法实现)

3.1 方法一:基于帧检测的视频裁剪

这是第一个脚本,它通过逐帧检测视频中的人物,并在发现人物时标记视频片段的开始和结束时间。当视频处理完成后,将使用FFmpeg将这些片段合并成一个新的视频文件。

# 导入必要的库
import cv2
from ultralytics import YOLO
import os
import ffmpeg
import time
from tqdm import tqdm
import subprocess

# 获取当前目录
current_directory = os.getcwd()

# 加载YOLOv8模型
model_path = os.path.join(current_directory, 'yolov8n.pt')
model = YOLO(model_path)  # 使用当前目录中的YOLOv8模型

# 定义视频文件路径和输出文件夹
input_video_path = '27.mp4'
output_folder = 'output27/'

# 确保输出文件夹存在
if not os.path.exists(output_folder):
    os.makedirs(output_folder)

# 打开视频文件
cap = cv2.VideoCapture(input_video_path)

# 获取视频的基本信息
fps = cap.get(cv2.CAP_PROP_FPS)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 获取总帧数

# 初始化变量
start_time = None
clip_count = 0
min_clip_duration = 0.5  # 最小片段长度阈值,单位为秒

def extract_video_segment(input_path, start_time, end_time, output_path):
    (
        ffmpeg
        .input(input_path, ss=start_time, to=end_time)
        .output(output_path, c='copy', an=None)
        .run(overwrite_output=True)
    )

# 开始计时
start_time_total = time.time()

# 创建进度条
pbar = tqdm(total=total_frames, desc="Processing Frames")

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break

    # 将帧转换为YOLOv8可以处理的格式
    results = model(frame)

    # 检查是否有人的检测结果
    has_person = False
    for result in results:
        for box in result.boxes:
            if box.cls == 0:  # 0 对应 'person' 类别
                has_person = True
                break
        if has_person:
            break

    # 如果有人的检测结果
    if has_person:
        if start_time is None:
            start_time = cap.get(cv2.CAP_PROP_POS_MSEC) / 1000.0
    else:
        if start_time is not None:
            end_time = cap.get(cv2.CAP_PROP_POS_MSEC) / 1000.0
            clip_duration = end_time - start_time
            if clip_duration >= min_clip_duration:
                output_path = f"{output_folder}clip_{clip_count}.mp4"
                extract_video_segment(input_video_path, start_time, end_time, output_path)
                clip_count += 1
            start_time = None

    # 更新进度条
    pbar.update(1)

# 处理最后一个片段
if start_time is not None:
    end_time = cap.get(cv2.CAP_PROP_POS_MSEC) / 1000.0
    clip_duration = end_time - start_time
    if clip_duration >= min_clip_duration:
        output_path = f"{output_folder}clip_{clip_count}.mp4"
        extract_video_segment(input_video_path, start_time, end_time, output_path)

# 释放视频捕获对象
cap.release()

# 关闭进度条
pbar.close()

# 结束计时
end_time_total = time.time()
total_time = end_time_total - start_time_total

print(f"处理完成,总运行时间: {total_time:.2f} 秒")

# 生成 input.txt 文件
def generate_input_txt(folder_path, output_file):
    with open(output_file, 'w') as f:
        for filename in sorted(os.listdir(folder_path)):
            if filename.endswith(('.mp4', '.avi', '.mkv')):
                video_path = os.path.join(folder_path, filename)
                f.write(f"file '{video_path}'\n")

# 合并视频
def merge_videos(input_file, output_video_path):
    command = [
        'ffmpeg',
        '-f', 'concat',
        '-safe', '0',
        '-i', input_file,
        '-c', 'copy',  # 直接复制视频和音频流,不重新编码
        output_video_path
    ]
    subprocess.run(command, check=True)

folder_path = output_folder  # 你的视频文件夹路径
output_file = 'input.txt'  # 生成的 input.txt 文件路径
output_video_path = 'output27.mp4'  # 合并后的视频输出路径

# 生成 input.txt 文件
generate_input_txt(folder_path, output_file)

# 定义 input_file 变量
input_file = output_file

# 合并视频
merge_videos(input_file, output_video_path)

print("视频合并完成")

运行后如下,1个G的视频完整处理时间大概二十多分钟,最好用gpu跑cpu跑要慢很多,我用的4060跑的,cuda版本是12.1的。

裁剪出来的很多包含人的片段
​​
视频裁剪完毕

3.2 方法二:基于帧提取和目标检测的视频裁剪

第二个个方法则首先将视频的每一帧提取出来,然后使用YOLOv8模型检测每帧中是否包含人物,筛选只保留包含人物的帧,最后,将所有包含人物的帧重新组合成一个新的视频。

# 导入必要的库
import cv2
from ultralytics import YOLO
import os
import numpy as np
from tqdm import tqdm
import subprocess

# 加载YOLOv8模型
model = YOLO('yolov8n.pt')  # 使用YOLOv8模型

# 定义视频文件路径
input_video_path = '14.mp4'
output_video_path = 'output_14.mp4'

# 打开视频文件
cap = cv2.VideoCapture(input_video_path)

# 获取视频的基本信息
fps = cap.get(cv2.CAP_PROP_FPS)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 获取总帧数

# 创建临时文件夹
temp_folder = 'temp_frames'
if not os.path.exists(temp_folder):
    os.makedirs(temp_folder)

# 提取视频帧
frame_count = 0
while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
    frame_path = os.path.join(temp_folder, f'frame_{frame_count:04d}.jpg')
    cv2.imwrite(frame_path, frame)
    frame_count += 1

# 释放视频捕获对象
cap.release()

# 使用YOLOv8进行目标检测
person_frames = []
pbar = tqdm(total=frame_count, desc="Detecting People")

for i in range(frame_count):
    frame_path = os.path.join(temp_folder, f'frame_{i:04d}.jpg')
    results = model(frame_path)
    for result in results:
        for box in result.boxes:
            if box.cls == 0:  # 0 对应 'person' 类别
                person_frames.append(frame_path)
                break
    pbar.update(1)

pbar.close()

# 重新组合视频
output_frames_folder = 'output_frames'
if not os.path.exists(output_frames_folder):
    os.makedirs(output_frames_folder)

for i, frame_path in enumerate(person_frames):
    output_frame_path = os.path.join(output_frames_folder, f'frame_{i:04d}.jpg')
    os.rename(frame_path, output_frame_path)

# 使用FFmpeg重新组合视频
subprocess.run([
    'ffmpeg', '-framerate', str(fps), '-i', os.path.join(output_frames_folder, 'frame_%04d.jpg'),
    '-c:v', 'libx264', '-r', '30', '-pix_fmt', 'yuv420p', output_video_path
])

# 清理临时文件
for file_name in os.listdir(temp_folder):
    file_path = os.path.join(temp_folder, file_name)
    os.remove(file_path)
os.rmdir(temp_folder)

for file_name in os.listdir(output_frames_folder):
    file_path = os.path.join(output_frames_folder, file_name)
    os.remove(file_path)
os.rmdir(output_frames_folder)

print(f"处理完成,新视频文件保存在 {output_video_path}")

运行后结果如下:

帧合成视频过程
​​​​​​
运行结束

性能比较

第一种方法比第二种方法运行得快得多,原因如下:

  1. I/O操作减少:第一个脚本直接在内存中处理视频帧,而不需要将每一帧写入磁盘。这大大减少了I/O操作,提高了处理速度。
  2. 内存使用:第一个脚本在处理过程中不需要额外的内存来存储帧图像,因为它直接在视频流上进行操作。
  3. FFmpeg的使用:第一个脚本利用FFmpeg的高效视频处理能力,直接在视频文件上进行裁剪,而不需要先将帧提取出来再重新编码。

不过第二个脚本相较于第一个更加灵活一些,提取出来的帧可以用做其他分析。

闲得无聊,尝试用纯OD脚本做一个金盾2019的提取 详细分析不多介绍 008AD04D . E8 8299B5FF call 金盾19播.004069D4 008AD052 . 8BC7 mov eax,edi 008AD054 . 99 cdq 008AD055 . 034424 08 add eax,dword ptr ss:[esp+0x8] 008AD059 . 135424 0C adc edx,dword ptr ss:[esp+0xC] 008AD05D . 52 push edx 008AD05E . 50 push eax 008AD05F . 8BC3 mov eax,ebx 008AD061 . E8 9A75BBFF call 金盾19播.00464600 008AD066 . 8B4424 18 mov eax,dword ptr ss:[esp+0x18] 008AD06A . 50 push eax 008AD06B . E8 D00EB6FF call 金盾19播.0040DF40 008AD070 . 59 pop ecx 008AD071 . 8BC7 mov eax,edi //下个硬件断点,视频提取的关键位置 008AD073 . 83C4 28 add esp,0x28 008AD076 . 5D pop ebp 008AD077 . 5F pop edi 008AD078 . 5E pop esi 008AD079 . 5B pop ebx 008AD07A . C3 retn 堆栈: 0012EF6C 04A5B820 buffer 0012EF70 00008000 0012EF74 00000000 2019.zip (294 Bytes, 下载次数: 832) 本主题由 Sound 于 2016-4-20 15:32 移动 免费评分 参与人数 8 吾爱币 +7 热心值 +6 收起理由 fhangong + 1 我很赞同! 无极166 + 1 + 1 谢谢@Thanks! felixwu311 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩! ddddddao + 1 + 1 谢谢@Thanks! 逍遥枷锁 + 1 谢谢@Thanks! 那天晚上 + 1 + 1 用心讨论,共获提升! haifeng0220 + 1 + 1 不懂啊。。。。。 slk + 1 我很赞同! 查看全部评分 收藏收藏24 免费评分免费评分 分享淘帖 送鲜花送鲜花 扔鸡蛋扔鸡蛋 发送到手机穿越 发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案; 如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】; 如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人! 论坛附件只能通过单线程下载,迅雷等多线程工具不能正常下载! 回复 举报 jj8426 0 主题 206 帖子 103 积分 锋芒初露 Rank: 1 UID472379精华0 威望0 点 吾爱币866 CB 热心值0 点 听众0 贡献值0 点 违规0 次 在线时间354 小时 注册时间2016-1-19 最后登录2017-1-9 收听TA 沙发 发表于 2016-4-16 21:23 | 只看该作者 视频是什么类型的 发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案; 如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】; 如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人! 【吾爱破解论坛导航帖】 - [让你快速融入吾爱破解大家庭] 回复 支持 反对 免费评分 举报 xiawan 65 主题 2219 帖子 1153 积分 凤毛麟角 Rank: 5Rank: 5 UID381546精华0 威望3 点 吾爱币2692 CB 热心值46 点 听众18 贡献值0 点 违规0 次 在线时间862 小时 注册时间2015-2-15 最后登录2017-1-10 收听TA 藤椅 发表于 2016-4-16 21:23 | 只看该作者 违规了,进了小黑屋,不能发帖怎么办? 膜拜神贴,后面的请保持队形~ 别把自己太当人,也别把别人不当人! 论坛账号被盗严重,教你如何保障社区帐号的安全! 回复 支持 反对 免费评分 举报 孙忠山 22 主题 242 帖子 149 积分 锋芒初露 Rank: 1 UID243745精华0 威望0 点 吾爱币346 CB 热心值34 点 听众43 贡献值0 点 违规0 次 在线时间438 小时 注册时间2013-3-13 最后登录2017-1-8 收听TA 板凳 楼主| 发表于 2016-4-16 21:25 | 只看该作者 |楼主 《站点帮助文档》有什么问题来这里看看吧,这里有你想知道的内容! jj8426 发表于 2016-4-16 21:23 视频是什么类型的 脚本仅用于能在本机播放的跳加密视频提取。 发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案; 如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】; 如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人! 关于如何获得论坛C币和威望! 回复 支持 反对 免费评分 举报 Lewtq 0 主题 178 帖子 89 积分 锋芒初露 Rank: 1 UID451320精华0 威望0 点 吾爱币390 CB 热心值0 点 听众0 贡献值0 点 违规0 次 在线时间96 小时 注册时间2015-11-11 最后登录2016-12-28 收听TA 报纸 发表于 2016-4-16 21:29 | 只看该作者 无论什么加密的视频都可以提取吗? 发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案; 如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】; 如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人! 如何快速判断一个文件是否为病毒! 回复 支持 反对 免费评分 举报 chinasmu 14 主题 458 帖子 247 积分 前途无量 Rank: 3Rank: 3 UID115088精华0 威望0 点 吾爱币594 CB 热心值22 点 听众8 贡献值0 点 违规0 次 在线时间262 小时 注册时间2010-5-2 最后登录2017-1-10 收听TA 地板 发表于 2016-4-16 21:42 | 只看该作者 前排招租 呼吁大家发布原创作品添加吾爱破解论坛标示! 回复 支持 反对 免费评分 举报 851365960 11 主题 1212 帖子 622 积分 出类拔萃 Rank: 4 UID169181精华0 威望0 点 吾爱币62 CB 热心值18 点 听众8 贡献值0 点 违规0 次 在线时间1111 小时 注册时间2012-2-5 最后登录2016-12-23 活跃会员奖 收听TA 7# 发表于 2016-4-16 22:39 | 只看该作者 谢谢分享。 如何快速赚到 CB,而且不会被关进小黑屋! 回复 支持 反对 免费评分 举报 水立方 10 主题 1665 帖子 864 积分 凤毛麟角 Rank: 5Rank: 5 UID424168精华0 威望0 点 吾爱币2877 CB 热心值38 点 听众7 贡献值0 点 违规0 次 在线时间636 小时 注册时间2015-7-21 最后登录2017-1-10 收听TA 8# 发表于 2016-4-16 23:19 | 只看该作者 谢谢分享。 发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案; 如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】; 如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人! 回复 支持 反对 免费评分 举报 84852153 2 主题 541 帖子 273 积分 前途无量 Rank: 3Rank: 3 UID485729精华0 威望0 点 吾爱币688 CB 热心值2 点 听众21 贡献值0 点 违规0 次 在线时间407 小时 注册时间2016-3-13 最后登录2017-1-10 收听TA 9# 发表于 2016-4-17 00:14 | 只看该作者 还以为是软件 谢谢分享。 V ha84852513 回复 支持 反对 免费评分 举报 破解粉丝 2 主题 156 帖子 78 积分 锋芒初露 Rank: 1 UID408460精华0 威望0 点 吾爱币1215 CB 热心值0 点 听众0 贡献值0 点 违规0 次 在线时间310 小时 注册时间2015-6-3 最后登录2017-1-10 收听TA 10# 发表于 2016-4-17 06:23 | 只看该作者 只 有一个osc文件,如何操作提取?完全不懂! 发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案; 如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】; 如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人! 回复 支持 反对 免费评分 举报 下一页 » 12345678 1 / 8 页下一页返回列表发新帖回复 高级模式 BColorImageLinkQuoteCodeSmilies@朋友| 本版积分规则发表回复 将此回复同步到 腾讯微博 | 回帖并转播 回帖后跳转到最后一页 免责声明: 吾爱破解所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。 Mail To:Service@52PoJie.Cn RSS订阅|手机版|小黑屋|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 ) GMT+8, 2017-1-10 17:41 Powered by Discuz! © 2001-2017 Comsenz Inc.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值