You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何基于react-native-sound实现录制音频的指定值升降调调整?

React Native音频升降调的可行解决方案

嘿,我完全懂你现在的困境——用react-native-sound做音频升降调确实有点棘手,那个Android的PR还没合并,iOS端更是没原生支持。别着急,给你几个靠谱的方向,覆盖双平台的解决方案:

一、封装原生模块,直接调用原生音频API

这是最灵活、最稳定的方案,能完全自定义升降调逻辑,双平台都能实现:

  • iOS端:用AVAudioEngine实现
    就像你提到的,AVAudioEngine是iOS原生处理音频效果的利器,核心是用AVAudioUnitTimePitch节点来调整音高,还能单独控制音高不影响播放速度。你可以封装一个React Native原生模块,核心逻辑大概是:

    1. 初始化AVAudioEngineAVAudioPlayerNode
    2. 添加AVAudioUnitTimePitch变调节点,设置pitch参数(正负值对应升降调,比如+12是升八度,-6是降半八度)
    3. 连接节点链,加载音频文件并播放

    给你一段iOS原生模块的简化示例:

    import AVFoundation
    import React
    
    @objc(AudioPitchHandler)
    class AudioPitchHandler: NSObject, RCTBridgeModule {
      static func moduleName() -> String { return "AudioPitchHandler" }
      static func requiresMainQueueSetup() -> Bool { return true }
    
      private var audioEngine: AVAudioEngine?
      private var playerNode: AVAudioPlayerNode?
    
      @objc func playAudioWithPitch(_ filePath: String, pitch: Float, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
        // 先停止之前的播放
        audioEngine?.stop()
        playerNode?.stop()
    
        audioEngine = AVAudioEngine()
        playerNode = AVAudioPlayerNode()
        let pitchEffect = AVAudioUnitTimePitch()
        pitchEffect.pitch = pitch // 设置升降调数值
        pitchEffect.rate = 1.0 // 保持播放速度不变
    
        guard let engine = audioEngine, let player = playerNode else {
          reject("INIT_ERROR", "Failed to initialize audio components", nil)
          return
        }
    
        engine.attach(player)
        engine.attach(pitchEffect)
        engine.connect(player, to: pitchEffect, format: nil)
        engine.connect(pitchEffect, to: engine.mainMixerNode, format: nil)
    
        do {
          let audioURL = URL(fileURLWithPath: filePath)
          let audioFile = try AVAudioFile(forReading: audioURL)
          player.scheduleFile(audioFile, at: nil)
          try engine.start()
          player.play()
          resolve(nil)
        } catch {
          reject("PLAY_ERROR", error.localizedDescription, error)
        }
      }
    
      @objc func stopAudio() {
        audioEngine?.stop()
        playerNode?.stop()
      }
    }
    

    然后在React Native里调用这个模块:

    import { NativeModules } from 'react-native';
    const { AudioPitchHandler } = NativeModules;
    
    // 示例:升3个半音播放音频
    AudioPitchHandler.playAudioWithPitch(filePath, 3.0)
      .catch(error => console.error("播放失败:", error));
    
    // 停止播放
    // AudioPitchHandler.stopAudio();
    
  • Android端:参考未合并PR或用ExoPlayer
    你可以把那个未合并的PR里的逻辑抽出来,封装成自己的原生模块;或者用更强大的ExoPlayer,它支持音频变调(通过AudioProcessor或者PitchShifter相关API),稳定性比SoundPool更好。

二、切换到支持变调的第三方音频库

如果不想自己写原生代码,可以试试这些现成的库:

  • react-native-track-player:这个库功能很全,支持自定义音频效果,你可以通过它的插件系统或者原生扩展来实现升降调,文档里有相关的音频处理指引。
  • react-native-sound-player(注意和你用的react-native-sound不是同一个):部分版本支持通过原生方法设置音高参数,你可以去查它的API文档,看看有没有setPitch之类的方法。

三、前端层面用Web Audio API处理

如果你的音频文件不大,也可以在JS层用Web Audio API处理:

  1. 把音频文件转换成ArrayBuffer
  2. AudioContext加载音频,创建PitchShift节点(或者自己实现变调算法,比如相位声码器)
  3. 播放处理后的音频

不过这个方案要注意性能问题,大文件可能会有卡顿,而且Android端的JS环境对Web Audio API的兼容性可能不如iOS。

总的来说,自定义原生模块是最推荐的方案,能保证双平台的稳定性和灵活性;如果想快速验证,先试试第三方库;小文件场景可以考虑Web Audio API。

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

火山引擎 最新活动