You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python OpenCV将处理后视频帧写入新视频输出损坏如何解决

问题原因

你的代码出现视频损坏的核心问题有以下几个:

  • 拼写错误:定义分辨率时的hieght是错误拼写,实际传入VideoWriter的高参数无效
  • 硬编码分辨率和帧率:你固定写了1280*720、30fps,但实际读取的视频流/摄像头流的参数不一定和这个匹配,VideoWriter要求写入的帧尺寸必须和初始化时设定的尺寸完全一致,参数不匹配就会生成损坏文件
  • 流读取方式错误:pafy拿到的视频流不能直接调用read()方法,需要先转成OpenCV的VideoCapture对象才能正常读帧
  • 未定义logo叠加坐标:代码中的x、y变量没有赋值,运行时会直接报错,无法正常写入有效帧
  • 无资源释放逻辑:没有循环退出条件,也没有在结束后调用release()方法释放VideoWriter对象,会导致视频文件头写入不完整,生成的文件无法正常播放
  • 透明logo处理错误:如果你的logo是带透明通道的png,直接赋值覆盖会丢失alpha信息,出现黑边
最优实现方案

该实现同时兼容YouTube流、本地视频文件、摄像头流三种场景,自动适配源流参数,支持带透明通道的logo叠加,代码如下:

import cv2
import pafy

# 1. 加载logo,保留alpha通道
logo = cv2.imread('logo.png', cv2.IMREAD_UNCHANGED)
logo_h, logo_w = logo.shape[:2]
# 定义logo叠加的左上角坐标,这里设置为左上角,可自行调整
x_offset = 10
y_offset = 10

# 2. 初始化视频流,以下三种选其一即可
## 选项1:读取YouTube流
url = "https://www.youtube.com/watch?v=vDHtypVwbHQ"
video = pafy.new(url)
best = video.getbest(preftype="mp4")
cap = cv2.VideoCapture(best.url)
## 选项2:读取本地摄像头,0是默认摄像头设备号
# cap = cv2.VideoCapture(0)
## 选项3:读取本地视频文件
# cap = cv2.VideoCapture("test.mp4")

# 3. 动态获取源流参数,不用硬编码
frame_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS) if cap.get(cv2.CAP_PROP_FPS) > 0 else 30 # 异常情况默认30fps

# 4. 初始化VideoWriter
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
video_writer = cv2.VideoWriter('output.mp4', fourcc, fps, (frame_w, frame_h))

frame_no = 1
while cap.isOpened():
    ret, frame = cap.read()
    # 读帧失败就退出循环,比如流结束、摄像头断开
    if not ret:
        break
    
    # 5. 叠加logo,兼容带透明通道的png
    if logo.shape[2] == 4:
        alpha = logo[:, :, 3] / 255.0
        for c in range(3):
            frame[y_offset:y_offset+logo_h, x_offset:x_offset+logo_w, c] = \
                alpha * logo[:, :, c] + (1 - alpha) * frame[y_offset:y_offset+logo_h, x_offset:x_offset+logo_w, c]
    else:
        # 无透明通道直接覆盖
        frame[y_offset:y_offset+logo_h, x_offset:x_offset+logo_w] = logo
    
    # 写入帧
    video_writer.write(frame)
    # 保存处理后的帧为图片的逻辑可自行在此补充
    frame_no += 1

    # 本地测试时按q键可提前退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 必须释放所有资源,否则视频会损坏
cap.release()
video_writer.release()
cv2.destroyAllWindows()

内容的提问来源于stack exchange,提问作者codebot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 12:15:08