找回密码
 立即注册
搜索
查看: 27|回复: 0

pyaudio录音

[复制链接]

52

主题

0

回帖

228

积分

管理员

积分
228
发表于 2025-8-17 20:43:11 | 显示全部楼层 |阅读模式
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()
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

SKYPIEA

GMT+8, 2025-9-7 13:47 , Processed in 0.045701 second(s), 19 queries .

快速回复 返回顶部 返回列表