本文目录导读:

我来分享几个Python视频转码的实用案例,主要使用moviepy和ffmpeg-python库。
基础环境安装
pip install moviepy ffmpeg-python # 还需要安装FFmpeg(系统层面)
使用moviepy进行视频格式转换
基础转换案例
from moviepy.editor import VideoFileClip
import os
def convert_video_basic(input_path, output_path):
"""
基础视频格式转换
"""
try:
# 加载视频
video = VideoFileClip(input_path)
# 转换并保存
video.write_videofile(
output_path,
codec='libx264', # 视频编码
audio_codec='aac', # 音频编码
fps=30, # 帧率
bitrate='2000k' # 比特率
)
video.close()
print(f"转换完成: {output_path}")
except Exception as e:
print(f"转换失败: {e}")
# 使用示例
convert_video_basic('input.avi', 'output.mp4')
批量转换案例
import glob
from moviepy.editor import VideoFileClip
from concurrent.futures import ThreadPoolExecutor
import os
def batch_convert_videos(input_dir, output_dir, target_format='mp4'):
"""
批量转换视频格式
"""
# 创建输出目录
os.makedirs(output_dir, exist_ok=True)
# 获取所有视频文件
video_extensions = ['*.avi', '*.mov', '*.mkv', '*.flv', '*.wmv']
video_files = []
for ext in video_extensions:
video_files.extend(glob.glob(os.path.join(input_dir, ext)))
def convert_single(video_path):
try:
# 生成输出文件名
filename = os.path.basename(video_path)
name_without_ext = os.path.splitext(filename)[0]
output_path = os.path.join(output_dir, f"{name_without_ext}.{target_format}")
# 转换视频
video = VideoFileClip(video_path)
video.write_videofile(
output_path,
codec='libx264',
audio_codec='aac',
preset='medium',
logger=None # 关闭日志
)
video.close()
print(f"转换成功: {filename}")
except Exception as e:
print(f"转换失败 {video_path}: {e}")
# 多线程处理
with ThreadPoolExecutor(max_workers=4) as executor:
executor.map(convert_single, video_files)
# 使用示例
batch_convert_videos('./input_videos/', './output_videos/')
使用ffmpeg-python进行转换
高级转换案例
import ffmpeg
import os
def convert_video_ffmpeg(input_path, output_path, options=None):
"""
使用ffmpeg进行高级视频转换
"""
if options is None:
options = {
'vcodec': 'libx264',
'acodec': 'aac',
'b:v': '2000k',
'b:a': '192k',
'vf': 'scale=1920:1080', # 调整分辨率
'r': 30 # 帧率
}
try:
# 构建ffmpeg命令
stream = ffmpeg.input(input_path)
# 应用输出选项
stream = ffmpeg.output(stream, output_path, **options)
# 执行转换
ffmpeg.run(stream, overwrite_output=True, capture_stderr=True)
print(f"转换完成: {output_path}")
except ffmpeg.Error as e:
print(f"FFmpeg错误: {e.stderr.decode()}")
# 使用示例
options = {
'vcodec': 'libx264', # 视频编码
'acodec': 'aac', # 音频编码
'b:v': '3000k', # 视频比特率
'b:a': '192k', # 音频比特率
'vf': 'scale=-2:720', # 保持宽高比缩放到720p
'r': 24, # 帧率
'preset': 'fast', # 编码速度
'crf': 23 # 质量(0-51, 越低越好)
}
convert_video_ffmpeg('input.mp4', 'output.mkv', options)
视频压缩案例
def compress_video(input_path, output_path, target_size_mb=100):
"""
压缩视频到目标大小
"""
try:
# 获取原视频信息
probe = ffmpeg.probe(input_path)
video_info = next(s for s in probe['streams'] if s['codec_type'] == 'video')
# 获取视频时长
duration = float(probe['format']['duration'])
# 计算目标比特率
total_bits = target_size_mb * 8 * 1024 * 1024
video_bitrate = int((total_bits / duration) * 0.9) # 90%给视频
# 构建压缩参数
output_params = {
'vcodec': 'libx264',
'acodec': 'aac',
'b:v': f'{video_bitrate}k',
'maxrate': f'{int(video_bitrate * 1.5)}k',
'bufsize': f'{int(video_bitrate * 2)}k',
'preset': 'slow',
'crf': 28
}
# 执行压缩
stream = ffmpeg.output(
ffmpeg.input(input_path),
output_path,
**output_params
)
ffmpeg.run(stream, overwrite_output=True)
# 显示压缩结果
original_size = os.path.getsize(input_path) / (1024 * 1024)
compressed_size = os.path.getsize(output_path) / (1024 * 1024)
ratio = (1 - compressed_size / original_size) * 100
print(f"原视频大小: {original_size:.2f} MB")
print(f"压缩后大小: {compressed_size:.2f} MB")
print(f"压缩率: {ratio:.1f}%")
except Exception as e:
print(f"压缩失败: {e}")
# 使用示例
compress_video('input.mp4', 'compressed.mp4', target_size_mb=50)
实用工具函数
def get_video_info(filepath):
"""
获取视频信息
"""
try:
video = VideoFileClip(filepath)
info = {
'filename': os.path.basename(filepath),
'duration': video.duration,
'size': os.path.getsize(filepath) / (1024 * 1024), # MB
'width': video.size[0],
'height': video.size[1],
'fps': video.fps,
'audio': video.audio is not None
}
video.close()
return info
except Exception as e:
return {'error': str(e)}
def supported_formats():
"""
返回支持转换的格式列表
"""
return {
'输入格式': ['mp4', 'avi', 'mov', 'mkv', 'flv', 'wmv', 'webm'],
'输出格式': ['mp4', 'avi', 'mov', 'mkv', 'webm', 'gif'],
'推荐编码': {
'mp4': 'libx264 + aac',
'webm': 'libvpx + libvorbis',
'avi': 'mpeg4 + mp3'
}
}
# 使用示例
print(get_video_info('input.mp4'))
print(supported_formats())
完整示例:GUI版本
import tkinter as tk
from tkinter import filedialog, ttk
import threading
from moviepy.editor import VideoFileClip
class VideoConverterGUI:
def __init__(self, root):
self.root = root
self.root.title("视频格式转换工具")
self.root.geometry("500x400")
# 创建界面元素
self.create_widgets()
def create_widgets(self):
# 文件选择
tk.Label(self.root, text="选择视频文件:").pack(pady=10)
self.file_path = tk.StringVar()
tk.Entry(self.root, textvariable=self.file_path, width=50).pack(padx=20)
tk.Button(self.root, text="浏览", command=self.select_file).pack(pady=5)
# 输出格式选择
tk.Label(self.root, text="输出格式:").pack(pady=10)
self.output_format = tk.StringVar(value="mp4")
formats = ["mp4", "avi", "mov", "mkv", "webm"]
ttk.Combobox(self.root, textvariable=self.output_format,
values=formats, state="readonly").pack()
# 质量设置
tk.Label(self.root, text="视频质量:").pack(pady=10)
self.quality = tk.IntVar(value=50)
quality_scale = tk.Scale(self.root, from_=10, to=100,
variable=self.quality, orient=tk.HORIZONTAL,
length=300)
quality_scale.pack()
# 转换按钮
self.convert_btn = tk.Button(self.root, text="开始转换",
command=self.start_conversion)
self.convert_btn.pack(pady=20)
# 进度条
self.progress = ttk.Progressbar(self.root, length=300, mode='determinate')
self.progress.pack(pady=10)
# 状态显示
self.status_label = tk.Label(self.root, text="就绪")
self.status_label.pack()
def select_file(self):
filename = filedialog.askopenfilename(
title="选择视频文件",
filetypes=[("视频文件", "*.mp4 *.avi *.mov *.mkv *.flv *.wmv")]
)
if filename:
self.file_path.set(filename)
def start_conversion(self):
if not self.file_path.get():
self.status_label.config(text="请先选择视频文件")
return
# 在新线程中执行转换
thread = threading.Thread(target=self.convert_video)
thread.daemon = True
thread.start()
def convert_video(self):
try:
self.convert_btn.config(state="disabled")
self.status_label.config(text="正在转换...")
input_path = self.file_path.get()
base_name = os.path.splitext(input_path)[0]
output_path = f"{base_name}.{self.output_format.get()}"
# 根据质量设置比特率
bitrate = f"{self.quality.get() * 100}k"
video = VideoFileClip(input_path)
video.write_videofile(
output_path,
codec='libx264',
audio_codec='aac',
bitrate=bitrate,
logger=None
)
video.close()
self.status_label.config(text=f"转换完成: {os.path.basename(output_path)}")
except Exception as e:
self.status_label.config(text=f"转换失败: {str(e)}")
finally:
self.convert_btn.config(state="normal")
self.progress['value'] = 100
if __name__ == "__main__":
root = tk.Tk()
app = VideoConverterGUI(root)
root.mainloop()
性能优化建议
-
使用硬件加速:
options = { 'vcodec': 'h264_nvenc', # NVIDIA GPU加速 # 或 'vcodec': 'h264_amf' # AMD GPU加速 } -
多线程处理:
def convert_batch(input_files): with ThreadPoolExecutor(max_workers=4) as executor: list(executor.map(process_video, input_files)) -
内存优化:
# 处理大文件时分段读取 video = VideoFileClip(input_path, audio=True, target_resolution=(1080, 1920))
这些案例涵盖了从基础到高级的视频转码需求,你可以根据具体需求选择合适的实现方式,需要注意的是,视频转码是计算密集型任务,建议对处理时间有合理预期。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播