|
import pyaudio
import wave
import time
import os
import sys
def record_audio(duration, filename="output.wav", sample_rate=44100, channels=1, format=pyaudio.paInt16):
"""
录制指定时长的音频并保存为WAV文件
参数:
duration (float): 录制时长(秒)
filename (str): 输出文件名(默认为"output.wav")
sample_rate (int): 采样率(默认为44100Hz)
channels (int): 声道数(1=单声道, 2=立体声)
format: 音频格式(默认为16位整型)
"""
# 创建PyAudio对象
p = pyaudio.PyAudio()
# 打开音频流
stream = p.open(
format=format,
channels=channels,
rate=sample_rate,
input=True,
frames_per_buffer=1024
)
print(f"⏺ 开始录制音频,时长: {duration}秒...")
print("按下 Ctrl+C 可提前结束录制")
frames = []
start_time = time.time()
try:
# 录制音频
while time.time() - start_time < duration:
data = stream.read(1024, exception_on_overflow=False)
frames.append(data)
# 显示进度
elapsed = time.time() - start_time
progress = min(1.0, elapsed / duration)
bar_length = 50
block = int(round(bar_length * progress))
progress_bar = "[" + "█" * block + "-" * (bar_length - block) + "]"
percent = int(progress * 100)
sys.stdout.write(f"\r{progress_bar} {percent}% ({elapsed:.1f}/{duration}秒)")
sys.stdout.flush()
print("\n✅ 录制完成")
except KeyboardInterrupt:
actual_duration = time.time() - start_time
print(f"\n⏹ 录制提前结束,实际时长: {actual_duration:.1f}秒")
finally:
# 停止并关闭流
stream.stop_stream()
stream.close()
p.terminate()
# 保存为WAV文件
save_wav_file(frames, filename, sample_rate, channels, format)
return len(frames) * 1024 / sample_rate # 返回实际录制时长
def save_wav_file(frames, filename, sample_rate, channels, format):
"""保存音频帧为WAV文件"""
if not frames:
print("⚠️ 没有录制到音频数据")
return
# 确保目录存在
os.makedirs(os.path.dirname(filename), exist_ok=True)
# 设置WAV文件参数
wf = wave.open(filename, 'wb')
wf.setnchannels(channels)
wf.setsampwidth(pyaudio.get_sample_size(format))
wf.setframerate(sample_rate)
wf.writeframes(b''.join(frames))
wf.close()
file_size = os.path.getsize(filename) / (1024 * 1024) # MB
print(f"💾 音频已保存到: {filename} ({file_size:.2f} MB)")
def get_user_duration():
"""获取用户输入的录制时长"""
while True:
try:
duration = float(input("请输入录制时长(秒): "))
if duration <= 0:
print("❌ 时长必须大于0")
continue
return duration
except ValueError:
print("❌ 请输入有效的数字")
def get_filename():
"""获取用户输入的文件名"""
while True:
filename = input("请输入保存的文件名(默认为'recording.wav'): ").strip()
if not filename:
return r"H:\project\quant\recording.wav"
if not filename.endswith(".wav"):
filename += ".wav"
return filename
def main_menu():
"""主菜单界面"""
print("=" * 50)
print("PyAudio 录音工具")
print("=" * 50)
recordings = []
while True:
print("\n选项:")
print("1. 录制新音频")
print("2. 退出")
choice = input("请选择操作: ").strip()
if choice == "1":
# 录制新音频
duration = get_user_duration()
filename = get_filename()
# 高级设置选项
sample_rate = 16000
channels = 1
print(f"使用默认设置: 采样率={sample_rate}Hz, 声道数={channels}")
# 开始录制
actual_duration = record_audio(duration, filename, sample_rate, channels)
recordings.append({
"filename": filename,
"duration": actual_duration,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
})
elif choice == "2":
# 退出程序
print("\n感谢使用 PyAudio 录音工具")
if recordings:
print("\n录制历史:")
for i, rec in enumerate(recordings, 1):
print(f"{i}. {rec['filename']} - {rec['duration']:.1f}秒 ({rec['timestamp']})")
break
else:
print("❌ 无效的选择,请重新输入")
if __name__ == "__main__":
# 检查PyAudio是否可用
try:
p = pyaudio.PyAudio()
p.terminate()
except Exception as e:
print(f"❌ PyAudio初始化失败: {str(e)}")
sys.exit(1)
# 运行主菜单
main_menu() |
|