寻求支持暂停、恢复且无时长限制的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
相关产品推荐
相关产品推荐

