检测场景变化并将视频按场景分开

ops/2024/9/23 11:20:41/

1. PySceneDetect

PySceneDetect 是一个功能强大的 Python 库,专门用于检测视频中的场景变化。它可以自动检测视频中不同场景的切换,并返回场景的时间段。你可以使用这些信息来进一步将视频分割为不同的片段

通过 pip 安装 PySceneDetect:

pip install scenedetect[opencv]

处理一个视频:

from scenedetect import VideoManager, SceneManager
from scenedetect.detectors import ContentDetector# 设置视频文件路径
video_path = "input_video.mp4"# 创建视频管理器和场景管理器
video_manager = VideoManager([video_path])
scene_manager = SceneManager()# 使用内容检测器检测场景变化
scene_manager.add_detector(ContentDetector())# 开始处理视频
video_manager.set_downscale_factor()
video_manager.start()# 检测场景
scene_manager.detect_scenes(video_manager)# 获取检测到的场景列表
scene_list = scene_manager.get_scene_list()# 打印每个场景的起始和结束时间(秒)
for i, scene in enumerate(scene_list):print(f"Scene {i+1}: Start = {scene[0].get_seconds()} sec, End = {scene[1].get_seconds()} sec")

解释

  • ContentDetector() 用于检测视频中的场景变化(通过内容变化检测)。你可以调整 threshold 来控制检测灵敏度。
  • scene_list 会包含每个场景的起始和结束时间,你可以根据这些信息分割视频

批量处理视频

处理文件夹中的所有 .mp4 视频,并将时间戳信息存储到一个文本文件中

import os
from scenedetect import VideoManager, SceneManager
from scenedetect.detectors import ContentDetector# 定义函数来处理单个视频并记录时间戳
def process_video(video_path, output_file):# 创建视频管理器和场景管理器video_manager = VideoManager([video_path])scene_manager = SceneManager()# 使用内容检测器检测场景变化scene_manager.add_detector(ContentDetector())# 开始处理视频video_manager.set_downscale_factor()video_manager.start()# 检测场景scene_manager.detect_scenes(video_manager)# 获取检测到的场景列表scene_list = scene_manager.get_scene_list()# 写入时间戳信息到文件with open(output_file, 'a') as f:f.write(f"Video: {os.path.basename(video_path)}\n")for i, scene in enumerate(scene_list):start_time = scene[0].get_seconds()end_time = scene[1].get_seconds()f.write(f"Scene {i+1}: Start = {start_time:.2f} sec, End = {end_time:.2f} sec\n")f.write("\n")# 处理文件夹中的所有视频
def process_all_videos_in_folder(folder_path, output_file):# 清空或创建输出文件open(output_file, 'w').close()# 遍历文件夹中的所有文件for filename in os.listdir(folder_path):# 只处理 .mp4 文件if filename.endswith(".mp4"):video_path = os.path.join(folder_path, filename)print(f"Processing {filename}...")process_video(video_path, output_file)# 设置视频文件夹路径和输出文件路径
video_folder = "xxxxxx"  # 替换为你的视频文件夹路径
output_file = "scene_timestamps.txt"  # 场景切换时间戳的输出文件# 处理文件夹中的所有视频并记录场景切换时间戳
process_all_videos_in_folder(video_folder, output_file)print(f"场景切换时间戳已记录到 {output_file}")

代码说明:

  1. process_video 函数:

    • 该函数负责处理单个视频文件,使用 PySceneDetect 检测场景变化,并将每个场景的开始和结束时间戳记录到文件中。
    • 每个视频处理后,场景的开始和结束时间以秒为单位保存在文件中,文件会追加写入。
  2. process_all_videos_in_folder 函数:

    • 该函数负责遍历文件夹中的所有 .mp4 视频文件,并调用 process_video 函数处理每个视频。
    • 它将所有时间戳写入同一个文件,并清空文件以确保每次运行时都是新的记录。
  3. 输出文件 scene_timestamps.txt

    • 所有视频的场景切换时间戳将被记录在 scene_timestamps.txt 文件中。每个视频的时间戳会被标注为 Video: [文件名],每个场景的时间戳按 Scene [n]: Start = x sec, End = y sec 格式记录。

删除指定的场景:

需要安装 moviepy 库:pip install moviepy
这个脚本会读取你已有的场景时间戳信息,并自动处理所有视频,删除第一个场景。

利用现有的时间戳信息,通过视频处理库(如 moviepy)剪掉指定的视频片段。具体来说,你需要读取每个视频的第一个场景的结束时间(例如 Scene 1: End = xx.xx sec),并从这个时间点开始保留视频的剩余部分。

import os
import shutil
from moviepy.editor import VideoFileClip
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip# 定义函数处理单个视频文件,删除第一个场景
def process_video(video_path, scene_start, output_folder):# 提取视频的文件名和扩展名video_name = os.path.basename(video_path)output_video_path = os.path.join(output_folder, f"trimmed_{video_name}")# 使用 moviepy 获取视频的总时长with VideoFileClip(video_path) as video_clip:video_duration = video_clip.duration# 如果场景结束时间存在,则从该时间剪切到视频结束if scene_start is not None:ffmpeg_extract_subclip(video_path, scene_start, video_duration, targetname=output_video_path)print(f"Processed {video_name}, saved as {output_video_path}")else:print(f"No scene information for {video_name}. Retaining full video...")# 如果没有场景信息,保留原始视频文件shutil.copy(video_path, output_video_path)# 解析时间戳文件
def parse_timestamp_file(timestamp_file):video_scenes = {}# 打开并读取时间戳文件with open(timestamp_file, 'r') as file:current_video = Nonefor line in file:line = line.strip()if line.startswith("Video:"):# 获取视频文件名current_video = line.split(":")[1].strip()video_scenes[current_video] = []elif line.startswith("Scene 1:"):# 获取第一个场景的结束时间end_time_str = line.split("End =")[1].strip().replace(" sec", "")video_scenes[current_video].append(float(end_time_str))return video_scenes# 主函数
def main(video_folder, timestamp_file, output_folder):# 创建输出文件夹,如果不存在则创建if not os.path.exists(output_folder):os.makedirs(output_folder)# 解析时间戳文件,获取每个视频的第一个场景结束时间video_scenes = parse_timestamp_file(timestamp_file)# 遍历视频文件并处理for video_name, scene_times in video_scenes.items():video_path = os.path.join(video_folder, video_name)if os.path.exists(video_path):if scene_times:  # 如果有场景信息first_scene_end_time = scene_times[0]  # 获取第一个场景的结束时间# 处理视频,删除第一个场景process_video(video_path, first_scene_end_time, output_folder)else:# 没有场景信息,保留完整视频print(f"Retaining full video for {video_name} (no scene information).")output_video_path = os.path.join(output_folder, f"trimmed_{video_name}")shutil.copy(video_path, output_video_path)else:print(f"Video file {video_name} not found!")# 文件路径和文件夹
video_folder = "path/to/your/videos"  # 视频文件夹路径
timestamp_file = "timestamps.txt"     # 时间戳文件路径
output_folder = "path/to/output/videos"  # 输出文件夹路径# 运行主函数
main(video_folder, timestamp_file, output_folder)

代码说明:

  1. process_video():这个函数用于处理每个视频,使用 moviepy 库的 ffmpeg_extract_subclip 函数将视频从第一个场景结束时间点剪切到视频末尾。

  2. parse_timestamp_file():这个函数读取并解析你的时间戳文件,提取每个视频的第一个场景结束时间。

  3. main():主函数中,通过遍历 video_folder 中的所有视频,并根据 timestamp_file 中的时间戳对每个视频进行剪切操作,删除第一个场景并将其余部分保存到 output_folder

  4. 对于没有场景信息的文件:通过 shutil.copy() 函数将视频直接复制到输出文件夹中,不进行任何剪辑。当视频没有场景信息时,打印提示信息 Retaining full video for {video_name},并将原视频文件完整保留。

输入与输出:

  • 输入视频文件和时间戳文件,时间戳文件包含每个视频的场景时间段信息(如你的示例)。
  • 输出剪切掉第一个场景后的新视频,并保存到指定的 output_folder 中。

2. Shotdetect

Shotdetect 是另一个专门用于视频场景变化检测的工具,适用于复杂的视频场景切割。它基于阈值或视觉内容的变化来检测场景切换。

安装:

pip install shotdetect

使用:

shotdetect -i input_video.mp4 -o output/ detect-content

解释

  • -i 参数指定输入视频文件。
  • -o 参数指定输出目录。
  • detect-content 命令会根据视频内容检测场景变化,并将每个检测到的场景保存在输出目录中。

你还可以在检测后使用 split-video 选项自动分割视频:

shotdetect -i input_video.mp4 -o output/ detect-content split-video

这个命令会自动将每个检测到的场景分割为独立的视频文件,存储在输出目录中。

3. ffmpeg + 变化检测

如果你不想使用专门的 Python 库,还可以通过 ffmpeg 的场景检测功能。ffmpeg 可以根据视频帧的内容差异检测场景变化。它输出场景切换的时间戳,然后你可以使用这些时间戳来切割视频。

ffmpeg -i input_video.mp4 -filter:v "select='gt(scene,0.4)',showinfo" -f null - 2> scene_changes.txt

解释

  • 这个命令会输出场景切换的时间戳到 scene_changes.txt 文件中。
  • gt(scene,0.4) 参数控制场景变化检测的阈值,0.4 是阈值,可以根据需要调整。

之后你可以使用 ffmpeg 的切割命令来按场景分割视频。例如:

ffmpeg -i input_video.mp4 -ss [start_time] -to [end_time] -c copy output_clip.mp4


http://www.ppmy.cn/ops/113546.html

相关文章

Linux(CentOS8)服务器安装RabbitMQ

我安装了很久都没有成功, 各种问题, 每次的异常都不一样, 现将成功安装过程做个总结 安装前工作 确保已经安装了一些基础工具和组件库 下载安装包 https://www.erlang.org/patches/otp-24.3.4.5 https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.9.15/ra…

1分钟解决 -bash: mvn: command not found,在Centos 7中安装Maven

1分钟解决 -bash: mvn: command not found,在Centos 7中安装Maven 检查Java环境1 下载Maven2 解压Maven3 配置环境变量4 验证安装5 常见问题与注意事项6 总结 检查Java环境 Maven依赖Java环境,请确保系统已经安装了Java并配置了环境变量。可以通过以下命…

LeetCode讲解篇之220. 存在重复元素 III

文章目录 题目描述题解思路题解代码 题目描述 题解思路 我们可以考虑存储数组中连续indexDiff个数字,这样我们只需要在这连续的indexDiff个数字中查找相差小于等于valueDiff的两个数字的问题 对于该查找问题,我们可以考虑使用以valueDiff大小为一个桶&a…

六西格玛咨询:石油机械制造企业的成本控制与优化专家

一、石油机械制造行业现状及主要困扰 随着全球能源需求的日益增长,石油开采和生产设备需求不断增加,石油机械制造行业在过去数十年里得到了迅猛发展。然而,石油机械制造作为一个高度复杂且技术密集的行业,也面临着多重挑战。首先…

SQLServer日期和时间类型

1、本文内容 适用于: Microsoft Fabric Microsoft FabricWarehouse 中的 SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure SynapseAnalytics Analytics Platform System (PDW)SQL Analytics 终结点 SQL Server 支持以下日期和时间类型…

A. Make All Equal

time limit per test 1 second memory limit per test 256 megabytes You are given a cyclic array a1,a2,…,ana1,a2,…,an. You can perform the following operation on aa at most n−1n−1 times: Let mm be the current size of aa, you can choose any two adjac…

多线程篇六

多线程篇六 如笔者理解有误欢迎交流指正~⭐ 什么是单例模式? 单例模式是最常见的 设计模式. 顾名思义,单例模式指的就是单个实例的模式.(针对某些类只能使用一个对象的场景【如MySQL、JDBC、DataSource】) 设计模式 设计模式是…

GoFly快速开发框架/Go语言封装的图像相似性比较插件使用说明

说明 图像相似性搜索应用广泛、除了使用搜索引擎搜索类似图片外,像淘宝可以让顾客直接拍照搜索类似的商品信息、应用在商品购物上,也可以应用物体识别比如拍图识花等领域。还有在调研图片鉴权的方案,通过一张图片和图片库中的图片进行比对&a…