[Python] Raspberry Pi audio recording works alone, but not when recording video at the same...

Discussão em 'Python' iniciado por Stack, Maio 31, 2025.

  1. Stack

    Stack Membro Participativo

    I have a Raspberry Pi Zero 2W wired to an Adafruit MEMS microphone with a camera attached. I tested audio recording in a separate Python program and that works perfectly:

    import subprocess
    import threading
    import os

    audio_process = None
    stop_recording_flag = False
    audio_filename = "test.wav"

    def record_audio():
    global audio_process, stop_recording_flag

    env = os.environ.copy()
    env["HOME"] = os.path.expanduser("~")

    print("Recording... Type 'stop' and press Enter to stop.")

    audio_process = subprocess.Popen([
    "arecord", "-D", "dmic_sv", "-c", "2", "-r", "48000",
    "-f", "S32_LE", "-t", "wav", audio_filename
    ], env=env)

    # Wait until user types 'stop'
    while not stop_recording_flag and audio_process.poll() is None:
    pass

    if audio_process.poll() is None:
    print("Stopping recording...")
    audio_process.terminate()
    try:
    audio_process.wait(timeout=5)
    except subprocess.TimeoutExpired:
    audio_process.kill()

    print(f"Recording saved to {audio_filename}")

    def monitor_input():
    global stop_recording_flag
    while True:
    command = input().strip().lower()
    if command == "stop":
    stop_recording_flag = True
    break

    if __name__ == "__main__":
    t1 = threading.Thread(target=record_audio)
    t2 = threading.Thread(target=monitor_input)
    t1.start()
    t2.start()
    t1.join()
    t2.join()


    But when I tried implementing that into my main program that records audio and video, then muxes them, video works fine but there is no audio in either the audio.wav file or the video itself. I know the mic works, the muxxing works. I am fairly certain it's an issue with how I thread and start the audio recording (some parts of the code below are removed for readability):

    video_selected_index = 0
    is_recording = False
    framerate = 30
    video_filename = "/home/pi/video.h264"
    audio_wav_filename = "/home/pi/audio.wav"
    final_filename = ""
    picam = None
    audio_process = None
    audio_thread = None
    video_thread = None

    def record_audio():
    global audio_process, is_recording

    try:
    print(" [record_audio] Starting audio capture, Sir.")
    env = os.environ.copy()
    env["HOME"] = os.path.expanduser("~")

    audio_process = subprocess.Popen([
    "arecord", "-D", "dmic_sv", "-c", "2", "-r", "48000",
    "-f", "S32_LE", "-t", "wav", audio_wav_filename
    ], env=env)

    # Wait for is_recording to turn False
    while is_recording:
    time.sleep(0.1)

    if audio_process.poll() is None:
    print(" [record_audio] Terminating arecord…")
    audio_process.terminate()
    try:
    audio_process.wait(timeout=5)
    except subprocess.TimeoutExpired:
    audio_process.kill()

    print(f" [record_audio] Audio saved to {audio_wav_filename}, Sir.")

    except Exception as e:
    print(f" [record_audio] Exception, Sir: {e}")

    def start_recording(config):
    """
    Launch audio + video threads (non-daemon), with a slight stagger.
    """
    global is_recording, audio_thread, video_thread

    is_recording = True

    # Start UI updater thread (could remain daemon)
    threading.Thread(target=recording_ui_updater, daemon=True).start()

    # Create *non-daemon* threads for audio & video so they run fully
    audio_thread = threading.Thread(target=record_audio, daemon=False)
    video_thread = threading.Thread(target=record_video, args=(config,), daemon=False)

    # Start audio first, give it time to initialize DMIC
    audio_thread.start()
    time.sleep(0.1)

    # Now start video capture
    video_thread.start()

    def stop_recording():
    """
    Signal both threads to finish, then join.
    """
    global is_recording

    is_recording = False
    print(" [stop_recording] Signaled threads to stop.")
    recording_status("Muxing...")

    if audio_thread:
    audio_thread.join()

    # Give time for OS to flush file buffers
    time.sleep(0.5) # Crucial

    if video_thread:
    print(" [stop_recording] Joining video thread…")
    video_thread.join()

    print(" [stop_recording] Threads joined, proceeding to mux.")
    mux_audio_video()

    def show_take_video_menu():
    global video_selected_index, is_recording, picam
    try:
    picam = Picamera2()
    picam.configure(picam.create_still_configuration())
    picam.start()
    time.sleep(2) # Camera warm-up
    except Exception as e:
    print(f"Camera initialization failed: {e}")
    return

    while True:
    if not is_recording:
    # Draw resolution menu
    img = Image.new("RGB", (160, 80), "black")
    draw = ImageDraw.Draw(img)
    title = "Take Video"
    title_width = draw.textlength(title, font=font)
    draw.text(((160 - title_width) // 2, 2), title, font=font, fill="red")

    for i, (label, _) in enumerate(video_resolutions):
    prefix = "> " if i == video_selected_index else " "
    draw.text((10, 18 + i * 14), prefix + label, font=font, fill="red")
    display.display(img)

    # Button controls
    if GPIO.input(21) == GPIO.LOW: # UP
    wait_for_button_release(21)
    video_selected_index = (video_selected_index - 1) % len(video_resolutions)

    elif GPIO.input(12) == GPIO.LOW: # DOWN
    wait_for_button_release(12)
    video_selected_index = (video_selected_index + 1) % len(video_resolutions)

    elif GPIO.input(16) == GPIO.LOW: # SELECT
    wait_for_button_release(16)
    label, config = video_resolutions[video_selected_index]

    if is_recording:
    stop_recording()
    continue

    if label.lower() == "return":
    if is_recording:
    stop_recording()
    print("Exiting video menu.")
    picam.close()
    return

    if config:
    start_recording(config)

    time.sleep(0.1) # Input debounce delay

    def mux_audio_video():
    global final_filename, framerate
    timestamp = time.strftime("%Y%m%d_%H%M%S")
    final_filename = f"/home/pi/Videos/recording_{timestamp}.mp4"
    subprocess.run([
    "ffmpeg", "-y",
    "-framerate", str(framerate),
    "-i", video_filename,
    "-i", audio_wav_filename,
    "-metadata:s:v", "rotate=270",
    "-c:v", "copy",
    "-c:a", "aac",
    "-shortest", final_filename
    ], check=True)
    print(f"Muxed to {final_filename}")

    Continue reading...

Compartilhe esta Página