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

寻求支持暂停、恢复且无时长限制的Python简易录音方案

支持暂停/恢复的无时长限制Python录音方案

方案一:基于sounddevice + soundfile实现(推荐)

这个方案比官方示例更简洁,容易复用,原生支持暂停/恢复逻辑,无需预先设置时长:

依赖安装

pip install sounddevice soundfile numpy

完整可复用代码

import tkinter as tk
import sounddevice as sd
import soundfile as sf
import numpy as np
from queue import Queue

class AudioRecorder:
    def __init__(self, output_file="recording.wav"):
        self.output_file = output_file
        self.recording = False
        self.paused = False
        self.audio_queue = Queue()
        self.stream = None
        self.samplerate = sd.query_devices(None, 'input')['default_samplerate']
        self.channels = 2

    def audio_callback(self, indata, frames, time, status):
        if status:
            print(status, file=sys.stderr)
        if not self.paused:
            self.audio_queue.put(indata.copy())

    def start_recording(self):
        if not self.recording:
            self.recording = True
            self.paused = False
            # 启动录音流
            self.stream = sd.InputStream(
                samplerate=self.samplerate,
                channels=self.channels,
                callback=self.audio_callback
            )
            self.stream.start()
            # 启动保存线程(避免阻塞UI)
            self.save_thread = threading.Thread(target=self._save_audio)
            self.save_thread.start()

    def pause_recording(self):
        if self.recording and not self.paused:
            self.paused = True

    def resume_recording(self):
        if self.recording and self.paused:
            self.paused = False

    def stop_recording(self):
        if self.recording:
            self.recording = False
            self.stream.stop()
            self.stream.close()
            self.save_thread.join()

    def _save_audio(self):
        # 初始化音频文件
        with sf.SoundFile(self.output_file, mode='w', samplerate=self.samplerate, channels=self.channels) as file:
            while self.recording or not self.audio_queue.empty():
                while not self.audio_queue.empty():
                    file.write(self.audio_queue.get())

# UI部分
if __name__ == "__main__":
    import threading
    import sys

    window = tk.Tk()
    window.geometry('700x350')
    window.title('简易录音机')
    tk.Label(window, text="点击按钮控制录音", font=('bold', 20)).pack(pady=20)

    recorder = AudioRecorder("my_recording.wav")

    def start_cmd():
        recorder.start_recording()
        status_label.config(text="正在录音...")

    def pause_cmd():
        recorder.pause_recording()
        status_label.config(text="录音已暂停")

    def resume_cmd():
        recorder.resume_recording()
        status_label.config(text="恢复录音...")

    def stop_cmd():
        recorder.stop_recording()
        status_label.config(text="录音已停止,文件已保存")

    button_frame = tk.Frame(window)
    button_frame.pack(pady=10)

    tk.Button(button_frame, text='开始录音', bg='green', command=start_cmd, font=('bold', 15)).grid(row=0, column=0, padx=10)
    tk.Button(button_frame, text='暂停录音', bg='orange', command=pause_cmd, font=('bold', 15)).grid(row=0, column=1, padx=10)
    tk.Button(button_frame, text='恢复录音', bg='blue', command=resume_cmd, font=('bold', 15)).grid(row=0, column=2, padx=10)
    tk.Button(button_frame, text='停止录音', bg='red', command=stop_cmd, font=('bold', 15)).grid(row=0, column=3, padx=10)

    status_label = tk.Label(window, text="等待操作", font=('bold', 16))
    status_label.pack(pady=20)

    window.mainloop()

方案说明

  • 用Queue缓存录音数据,避免阻塞UI线程
  • 通过paused状态变量控制是否写入数据,实现暂停/恢复
  • 录音过程中自动保存到文件,无需预先设置时长
  • 代码模块化,AudioRecorder类可以直接在其他项目中复用

方案二:针对recorder库的分段拼接方案

如果你坚持使用recorder库,但该库原生不支持暂停/恢复功能,可以通过分段录音+后期拼接实现:

依赖安装

pip install recorder pydub

注意:需要额外安装ffmpeg并添加到系统PATH,否则pydub无法处理音频拼接。

简化版代码

import tkinter as tk
from tkinter import *
import recorder
from pydub import AudioSegment
import os

window = Tk()
window.geometry('700x350')
window.title('分段录音机')
Label(window,text="点击按钮控制录音",font=('bold',20)).pack(pady=20)

rec = recorder.Recorder(channels=2)
running = None
segment_files = []
current_segment = 0

def start_or_resume():
    global running, current_segment
    if running is not None:
        print('already running')
        return
    current_segment +=1
    seg_file = f'segment_{current_segment}.flac'
    segment_files.append(seg_file)
    running = rec.open(seg_file, 'wb')
    running.start_recording()
    status_label.config(text="正在录音...")

def pause():
    global running
    if running is not None:
        running.stop_recording()
        running.close()
        running = None
        status_label.config(text="录音已暂停")
    else:
        print('not running')

def stop():
    global running
    if running is not None:
        running.stop_recording()
        running.close()
        running = None
    # 拼接所有片段
    combined = AudioSegment.empty()
    for seg in segment_files:
        combined += AudioSegment.from_file(seg, format='flac')
    combined.export('combined_recording.flac', format='flac')
    # 删除临时片段
    for seg in segment_files:
        os.remove(seg)
    status_label.config(text="录音已停止,文件已拼接保存")

button_frame = Frame(window)
button_frame.pack(pady=10)

Button(button_frame,text='开始/恢复',bg='green',command=start_or_resume,font=('bold',15)).grid(row=0,column=0,padx=10)
Button(button_frame,text='暂停',bg='orange',command=pause,font=('bold',15)).grid(row=0,column=1,padx=10)
Button(button_frame,text='停止',bg='red',command=stop,font=('bold',15)).grid(row=0,column=2,padx=10)

status_label = Label(window, text="等待操作", font=('bold',16))
status_label.pack(pady=20)

window.mainloop()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 01:25:24