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

树莓派使用cv2.VideoWriter录制视频异常:时长缩短、播放加速且无声音

Hey there! Let's work through your two video recording issues on Raspberry Pi—shortened/fast-playing footage and missing audio—with practical fixes and code tweaks.


1. Fixing Shortened Video & Speed-Up Playback

The root cause here is almost always a mismatch between the frame rate you set for VideoWriter and the actual frame rate your Raspberry Pi camera is outputting. For example, if you hardcode 30fps but the camera only captures 6fps, 10 seconds of recording would only produce 60 frames—playing back at 30fps makes it feel like 2x speed and only 2 seconds long.

Here's how to fix it:

  • First, estimate your camera's real frame rate instead of guessing
  • Record based on total frame count (calculated from real fps + desired duration) instead of relying on time.sleep()

Modified Video-Only Code

import numpy as np
import cv2
import time

capture_duration = 10  # Desired recording length in seconds

# Initialize camera (0 = default Pi camera)
cap = cv2.VideoCapture(0)

# Estimate actual camera FPS (cap.get(CAP_PROP_FPS) is often inaccurate on Pi)
start_time = time.time()
frame_count = 0
for _ in range(30):
    ret, frame = cap.read()
    if ret:
        frame_count += 1
actual_fps = frame_count / (time.time() - start_time)
print(f"Detected camera FPS: {actual_fps:.2f}")

# Configure VideoWriter with matching FPS
fourcc = cv2.VideoWriter_fourcc(*'MJPG')  # MJPG is more stable on Pi than XVID
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
out = cv2.VideoWriter('fixed_video.avi', fourcc, actual_fps, (width, height))

# Calculate total frames needed for desired duration
total_frames = int(actual_fps * capture_duration)
captured_frames = 0

# Start recording loop
while captured_frames < total_frames:
    ret, frame = cap.read()
    if ret:
        out.write(frame)
        captured_frames += 1
        # Optional preview window
        cv2.imshow('Recording', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        print("Warning: Failed to capture a frame")
        break

# Cleanup
cap.release()
out.release()
cv2.destroyAllWindows()
print(f"Recording complete! Captured {captured_frames} frames over {time.time()-start_time:.2f} seconds")

2. Adding Audio to Your Recording

OpenCV's VideoWriter doesn't support audio recording at all—it only handles video frames. To add sound, you'll need to record audio separately with a Python audio library, then merge the video and audio files using ffmpeg.

Step 1: Install Dependencies

First, install required packages on your Pi:

sudo apt install ffmpeg portaudio19-dev
pip install sounddevice numpy scipy

Step 2: Combined Video + Audio Recording Code

This uses threads to record video and audio simultaneously, then merges them with ffmpeg:

import numpy as np
import cv2
import time
import sounddevice as sd
from scipy.io.wavfile import write
import threading
import subprocess
import os

capture_duration = 10

# --- Video Setup ---
cap = cv2.VideoCapture(0)
# Estimate real camera FPS
start_time = time.time()
frame_count = 0
for _ in range(30):
    ret, frame = cap.read()
    if ret:
        frame_count += 1
actual_fps = frame_count / (time.time() - start_time)
print(f"Camera FPS: {actual_fps:.2f}")

fourcc = cv2.VideoWriter_fourcc(*'MJPG')
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
video_out = cv2.VideoWriter('temp_video.avi', fourcc, actual_fps, (width, height))
total_frames = int(actual_fps * capture_duration)

# --- Audio Setup ---
audio_sample_rate = 44100
audio_channels = 2
audio_total_frames = int(audio_sample_rate * capture_duration)

def record_audio():
    """Record audio in a separate thread"""
    audio_data = sd.rec(audio_total_frames, samplerate=audio_sample_rate, channels=audio_channels, dtype='int16')
    sd.wait()  # Wait for recording to finish
    write('temp_audio.wav', audio_sample_rate, audio_data)

# Start audio recording thread
audio_thread = threading.Thread(target=record_audio)
audio_thread.start()

# --- Record Video ---
captured_frames = 0
while captured_frames < total_frames:
    ret, frame = cap.read()
    if ret:
        video_out.write(frame)
        captured_frames += 1
        cv2.imshow('Recording', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

# Cleanup video resources
cap.release()
video_out.release()
cv2.destroyAllWindows()

# Wait for audio recording to finish
audio_thread.join()

# Merge video and audio with ffmpeg
subprocess.run([
    'ffmpeg', '-y',  # Overwrite output file without prompting
    '-i', 'temp_video.avi',
    '-i', 'temp_audio.wav',
    '-c:v', 'copy',  # Reuse existing video codec (no re-encoding)
    '-c:a', 'aac',   # Encode audio to AAC (widely supported)
    'final_with_audio.mp4'
])

# Delete temporary files
os.remove('temp_video.avi')
os.remove('temp_audio.wav')

print("Final video with audio saved as final_with_audio.mp4")

Quick Additional Tips

  • If you still have issues with camera access, enable the camera in sudo raspi-config > Interface Options > Camera
  • Try adjusting the camera resolution manually with cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) and cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) if the auto-detected resolution is causing problems
  • For better performance, close any other apps using the camera before running your script

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:09:04