本文目录导读:

我来详细介绍Python处理视频文件的常用方法和案例。
安装必备库
# 核心视频处理库 pip install opencv-python # 视频读取、处理、写入 pip install moviepy # 视频编辑、剪辑、转换 pip install ffmpeg-python # FFmpeg封装 pip install imageio-ffmpeg # 视频解码支持
使用OpenCV处理视频
1 读取和播放视频
import cv2
# 打开视频文件
cap = cv2.VideoCapture('input.mp4')
# 检查是否成功打开
if not cap.isOpened():
print("无法打开视频文件")
exit()
# 获取视频信息
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print(f"帧率: {fps}")
print(f"分辨率: {width}x{height}")
print(f"总帧数: {total_frames}")
# 逐帧读取视频
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
# 显示当前帧
cv2.imshow('Video', frame)
frame_count += 1
# 按'q'键退出
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
2 视频转灰度
import cv2
def video_to_grayscale(input_path, output_path):
"""将彩色视频转换为灰度视频"""
cap = cv2.VideoCapture(input_path)
# 获取视频属性
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 创建视频写入器
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height), isColor=False)
while True:
ret, frame = cap.read()
if not ret:
break
# 转为灰度
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 写入视频
out.write(gray)
# 显示进度
print(f"处理中...", end='\r')
cap.release()
out.release()
cv2.destroyAllWindows()
print(f"\n处理完成: {output_path}")
# 使用示例
video_to_grayscale('input.mp4', 'output_gray.mp4')
3 视频裁剪和缩放
import cv2
def crop_and_resize_video(input_path, output_path, crop_rect, target_size):
"""
裁剪并缩放视频
crop_rect: (x, y, width, height) 裁剪区域
target_size: (width, height) 目标尺寸
"""
cap = cv2.VideoCapture(input_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, target_size)
x, y, w, h = crop_rect
target_w, target_h = target_size
while True:
ret, frame = cap.read()
if not ret:
break
# 裁剪
cropped = frame[y:y+h, x:x+w]
# 缩放
resized = cv2.resize(cropped, target_size)
out.write(resized)
cap.release()
out.release()
# 使用示例
crop_and_resize_video(
'input.mp4',
'output_cropped.mp4',
(100, 50, 500, 400), # 裁剪区域
(640, 480) # 目标尺寸
)
使用MoviePy处理视频
1 视频剪辑和拼接
from moviepy.editor import VideoFileClip, concatenate_videoclips
def clip_and_merge_videos():
"""剪辑并合并视频片段"""
# 加载视频
clip1 = VideoFileClip("video1.mp4").subclip(10, 20) # 截取10-20秒
clip2 = VideoFileClip("video2.mp4").subclip(5, 15) # 截取5-15秒
# 合并视频
final_clip = concatenate_videoclips([clip1, clip2])
# 输出视频
final_clip.write_videofile(
"merged_video.mp4",
codec="libx264",
audio_codec="aac"
)
# 使用示例
clip_and_merge_videos()
2 视频特效处理
from moviepy.editor import VideoFileClip, vfx
def add_video_effects(input_path, output_path):
"""为视频添加特效"""
# 加载视频
clip = VideoFileClip(input_path)
# 应用特效
# 慢速播放(0.5倍速)
slow_motion = clip.fx(vfx.speedx, 0.5)
# 添加颜色滤镜
color_effect = clip.fx(vfx.colorx, 1.5) # 增加饱和度
# 添加时间反转效果
reversed_clip = clip.fx(vfx.time_mirror)
# 合成最终视频(只使用一种效果作为示例)
final = slow_motion
# 输出视频
final.write_videofile(
output_path,
codec="libx264",
audio_codec="aac",
fps=24
)
# 使用示例
add_video_effects('input.mp4', 'output_effects.mp4')
3 视频添加文字和水印
from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip
def add_text_overlay(input_path, output_path):
"""为视频添加文字覆盖层"""
# 加载视频
video = VideoFileClip(input_path)
# 创建文字剪辑
txt_clip = TextClip(
"示例文字",
fontsize=70,
color='white',
font='Arial',
stroke_color='black',
stroke_width=2
)
# 设置文字位置和时长
txt_clip = txt_clip.set_position('center').set_duration(video.duration)
# 创建水印
watermark = TextClip(
"Watermark",
fontsize=30,
color='gray',
font='Arial',
opacity=0.5
)
watermark = watermark.set_position(('right', 'bottom')).set_duration(video.duration)
# 合成视频
final = CompositeVideoClip([video, txt_clip, watermark])
# 输出
final.write_videofile(
output_path,
codec="libx264",
audio_codec="aac"
)
# 使用示例
add_text_overlay('input.mp4', 'output_with_text.mp4')
视频分析案例
1 提取视频帧
import cv2
import os
def extract_frames(input_path, output_dir, frame_interval=30):
"""按帧间隔提取视频帧并保存为图片"""
# 创建输出目录
if not os.path.exists(output_dir):
os.makedirs(output_dir)
cap = cv2.VideoCapture(input_path)
frame_count = 0
saved_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
# 按帧间隔保存
if frame_count % frame_interval == 0:
filename = f"frame_{saved_count:06d}.jpg"
filepath = os.path.join(output_dir, filename)
cv2.imwrite(filepath, frame)
saved_count += 1
print(f"保存帧: {filename}")
frame_count += 1
cap.release()
print(f"总共提取了 {saved_count} 帧")
# 使用示例
extract_frames('input.mp4', 'extracted_frames/', frame_interval=30)
2 运动检测
import cv2
def motion_detection(input_path, output_path, threshold=500):
"""检测视频中的运动区域"""
cap = cv2.VideoCapture(input_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# 读取第一帧
ret, prev_frame = cap.read()
if not ret:
return
prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
prev_gray = cv2.GaussianBlur(prev_gray, (21, 21), 0)
while True:
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
# 计算帧差
frame_delta = cv2.absdiff(prev_gray, gray)
thresh = cv2.threshold(frame_delta, 25, 255, cv2.THRESH_BINARY)[1]
# 轮廓检测
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
if cv2.contourArea(contour) > threshold:
# 绘制运动区域
(x, y, w, h) = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
out.write(frame)
prev_gray = gray
cap.release()
out.release()
# 使用示例
motion_detection('input.mp4', 'output_motion.mp4')
3 人脸检测和模糊
import cv2
def face_detection_and_blur(input_path, output_path):
"""检测人脸并进行模糊处理"""
# 加载人脸检测模型
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
)
cap = cv2.VideoCapture(input_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
while True:
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 检测人脸
faces = face_cascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30)
)
# 对人脸区域进行模糊
for (x, y, w, h) in faces:
roi = frame[y:y+h, x:x+w]
blurred = cv2.GaussianBlur(roi, (99, 99), 30)
frame[y:y+h, x:x+w] = blurred
out.write(frame)
print("处理中...", end='\r')
cap.release()
out.release()
print(f"\n处理完成: {output_path}")
# 使用示例
face_detection_and_blur('input.mp4', 'output_face_blurred.mp4')
视频格式转换
import subprocess
import os
def convert_video_format(input_path, output_path, codec='libx264', crf=23):
"""使用FFmpeg转换视频格式"""
cmd = [
'ffmpeg',
'-i', input_path, # 输入文件
'-c:v', codec, # 视频编码器
'-crf', str(crf), # 质量参数(0-51,越小质量越高)
'-preset', 'medium', # 编码速度/质量平衡
'-c:a', 'aac', # 音频编码器
'-b:a', '128k', # 音频比特率
'-y', # 覆盖输出文件
output_path
]
try:
subprocess.run(cmd, check=True)
print(f"转换完成: {output_path}")
except subprocess.CalledProcessError as e:
print(f"转换失败: {e}")
# 使用示例
convert_video_format('input.mkv', 'output.mp4')
convert_video_format('input.mp4', 'output.avi', crf=28)
实用工具函数
import cv2
import os
from pathlib import Path
class VideoUtils:
"""视频处理工具类"""
@staticmethod
def get_video_info(video_path):
"""获取视频信息"""
cap = cv2.VideoCapture(video_path)
info = {
'fps': cap.get(cv2.CAP_PROP_FPS),
'width': int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
'height': int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)),
'total_frames': int(cap.get(cv2.CAP_PROP_FRAME_COUNT)),
'duration': cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS)
}
cap.release()
return info
@staticmethod
def compress_video(input_path, output_path, target_size_mb=50):
"""压缩视频到目标大小"""
info = VideoUtils.get_video_info(input_path)
# 计算目标比特率
duration = info['duration']
target_bitrate = int((target_size_mb * 8 * 1024 * 1024) / duration)
cmd = [
'ffmpeg',
'-i', input_path,
'-b:v', f'{target_bitrate}',
'-maxrate', f'{target_bitrate * 2}',
'-bufsize', f'{target_bitrate * 4}',
'-y',
output_path
]
subprocess.run(cmd, check=True)
print(f"压缩完成: {output_path}")
@staticmethod
def batch_convert(input_dir, output_dir, target_format='.mp4'):
"""批量转换视频格式"""
os.makedirs(output_dir, exist_ok=True)
video_extensions = ['.mp4', '.avi', '.mov', '.mkv', '.flv']
for file in Path(input_dir).iterdir():
if file.suffix.lower() in video_extensions:
output_path = Path(output_dir) / f"{file.stem}{target_format}"
convert_video_format(str(file), str(output_path))
# 使用示例
utils = VideoUtils()
# 获取视频信息
info = utils.get_video_info('input.mp4')
print(f"视频信息: {info}")
# 压缩视频
utils.compress_video('input.mp4', 'compressed.mp4', target_size_mb=30)
# 批量转换
utils.batch_convert('videos/', 'converted/', '.mp4')
注意事项
-
性能优化:
- 处理大视频时使用流式处理,避免加载整个视频到内存
- 考虑使用GPU加速(OpenCV的CUDA模块)
-
编解码器:
- 常用视频编码器:H.264 (libx264), H.265 (libx265), VP9
- 常用音频编码器:AAC, MP3
-
错误处理:
- 始终检查视频文件是否成功打开
- 处理可能损坏的视频文件
-
依赖管理:
- 确保安装了ffmpeg系统工具
- 使用虚拟环境管理Python依赖
这些案例覆盖了Python视频处理的主要场景,你可以根据自己的需求组合使用。