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

如何在Godot中实现录制创作旋律并导出为mp3、wav等音乐文件

Godot钢琴游戏录制导出音频实现方案

方案一:基于演奏时序生成音频(优先推荐)

这个方案不需要实时捕获音频输出,性能开销极低,适合所有音效为预分配固定资源的场景:

  • 第一步:全局维护一个演奏记录数组,每次玩家按下按键触发音效时,往数组里写入三个数据:触发的时间戳(相对于录制开始的时间,单位秒)、对应的音效AudioStreamSample对象、音效播放时长
  • 第二步:录制结束后,先计算所有音频混合后的总时长,初始化一个空的PCM数据数组,采样率统一用你项目音频设置的采样率(比如44100Hz)
  • 第三步:遍历所有演奏记录,把每个音效的PCM数据按触发时间偏移,混合到总PCM数组里,混合的时候注意不要超过16位音频的最大振幅,避免爆音
  • 第四步:手动拼接WAV文件头,把混合好的PCM数据写入文件即可得到WAV格式导出文件。WAV头为固定44字节结构,GDScript实现参考代码:
func write_wav_file(path: String, pcm_data: PackedByteArray, sample_rate: int = 44100, channels: int = 1, bit_depth: int = 16):
    var file = FileAccess.open(path, FileAccess.WRITE)
    if not file:
        return
    # 写RIFF头
    file.store_buffer("RIFF".to_ascii_buffer())
    file.store_32(36 + pcm_data.size())
    file.store_buffer("WAVE".to_ascii_buffer())
    # 写fmt子块
    file.store_buffer("fmt ".to_ascii_buffer())
    file.store_32(16)
    file.store_16(1) # PCM格式
    file.store_16(channels)
    file.store_32(sample_rate)
    file.store_32(sample_rate * channels * bit_depth / 8)
    file.store_16(channels * bit_depth / 8)
    file.store_16(bit_depth)
    # 写data子块
    file.store_buffer("data".to_ascii_buffer())
    file.store_32(pcm_data.size())
    file.store_buffer(pcm_data)
    file.close()
  • 第五步:如果需要导出MP3格式,引入适配你Godot版本的Lame编码GDExtension插件,把生成好的PCM数据传入Lame编码接口输出MP3文件即可。

方案二:实时捕获音频总线输出

如果你的游戏有实时音效处理(比如混响、变调)或者动态混音需求,可以用Godot自带的AudioEffectCapture实现录制:

  • 第一步:打开项目音频设置,在你输出音效的音频总线(一般是Master总线)上添加AudioEffectCapture效果
  • 第二步:录制开始时,获取该捕获效果的实例,调用clear_buffer()清空缓存
  • 第三步:录制过程中每帧调用get_buffer()获取捕获到的PCM数据,追加到全局的PCM存储数组里
  • 第四步:录制结束后,用方案一的WAV写入方法把PCM数据存为WAV文件,再按需转MP3即可。核心代码参考:
var capture_effect: AudioEffectCapture
var recorded_pcm: PackedByteArray

func _ready():
    # 索引0对应Master总线,索引0是总线的第一个效果
    capture_effect = AudioServer.get_bus_effect(0, 0)

func _process(delta):
    if 正在录制状态:
        var available_frames = capture_effect.get_frames_available()
        if available_frames > 0:
            var buffer = capture_effect.get_buffer(available_frames)
            recorded_pcm.append_array(buffer.to_byte_array())

注意事项

  • 如果你的所有音效都是提前导入的固定资源,优先使用方案一,不会因为录制导致游戏掉帧,也不会出现音画不同步的问题
  • 所有操作的采样率、声道数要和项目音频设置保持一致,避免出现音频变调、速度异常的问题
  • 多轨道混合时可以给每个声道的振幅乘以0.8左右的系数,避免多音同时触发时超过最大音量导致爆音

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 04:24:03