首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提高/增加文本到语音转换(AVSpeechUtterance)的音量以使其声音更大

提高/增加文本到语音转换(AVSpeechUtterance)的音量以使其声音更大
EN

Stack Overflow用户
提问于 2019-07-12 10:03:01
回答 3查看 1.1K关注 0票数 1

我有一个导航应用程序,它使用AVSpeechUtterance给出方向语音指令(例如“200英尺内左转”)。我像这样把音量调到了1。speechUtteranceInstance.volume = 1,但与来自iPhone的音乐或播客相比,音量仍然很低,特别是当声音是通过蓝牙或有线连接(如通过蓝牙连接到汽车)时。

有没有办法提高音量?(我知道以前在上有人问过这个问题,但到目前为止还没有找到适合我的解决方案。)

EN

回答 3

Stack Overflow用户

发布于 2020-02-18 04:06:50

经过更多的研究和尝试,我找到了一个很好的变通解决方案。

首先,我认为这是一个iOS错误。当以下所有条件都成立时,我发现语音指令本身也被回避(或者至少它听起来是回避的),导致语音指令以与回避的音乐相同的音量播放(因此太柔和而听不清楚)。

通过连接的蓝牙设备(如蓝牙头戴式耳机或蓝牙车载扬声器)通过background

  • Ducking audioSessionCategory

  • Playing a .duckOther播放音乐此背景音乐通过voiceUtterance

我找到的变通解决方案是将speechUtterance提供给AVAudioEngine。这只能在iOS13或更高版本的上执行,因为这样会添加.write method to AVSpeechSynthesizer

简而言之,我使用AVAudioEngineAVAudioUnitEQAVAudioPlayerNode,将AVAudioUnitEQ的globalGain属性设置为大约10 dB。这也有一些怪癖,但它们可以解决(请参阅代码注释)。

下面是完整的代码:

代码语言:javascript
复制
import UIKit
import AVFoundation
import MediaPlayer

class ViewController: UIViewController {

    // MARK: AVAudio properties
    var engine = AVAudioEngine()
    var player = AVAudioPlayerNode()
    var eqEffect = AVAudioUnitEQ()
    var converter = AVAudioConverter(from: AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatInt16, sampleRate: 22050, channels: 1, interleaved: false)!, to: AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatFloat32, sampleRate: 22050, channels: 1, interleaved: false)!)
    let synthesizer = AVSpeechSynthesizer()
    var bufferCounter: Int = 0

    let audioSession = AVAudioSession.sharedInstance()




    override func viewDidLoad() {
        super.viewDidLoad()



        let outputFormat = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatFloat32, sampleRate: 22050, channels: 1, interleaved: false)!
        setupAudio(format: outputFormat, globalGain: 0)



    }

    func activateAudioSession() {
        do {
            try audioSession.setCategory(.playback, mode: .voicePrompt, options: [.mixWithOthers, .duckOthers])
            try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
        } catch {
            print("An error has occurred while setting the AVAudioSession.")
        }
    }

    @IBAction func tappedPlayButton(_ sender: Any) {

        eqEffect.globalGain = 0
        play()

    }

    @IBAction func tappedPlayLoudButton(_ sender: Any) {
        eqEffect.globalGain = 10
        play()

    }

    func play() {
        let path = Bundle.main.path(forResource: "voiceStart", ofType: "wav")!
        let file = try! AVAudioFile(forReading: URL(fileURLWithPath: path))
        self.player.scheduleFile(file, at: nil, completionHandler: nil)
        let utterance = AVSpeechUtterance(string: "This is to test if iOS is able to boost the voice output above the 100% limit.")
        synthesizer.write(utterance) { buffer in
            guard let pcmBuffer = buffer as? AVAudioPCMBuffer, pcmBuffer.frameLength > 0 else {
                print("could not create buffer or buffer empty")
                return
            }

            // QUIRCK Need to convert the buffer to different format because AVAudioEngine does not support the format returned from AVSpeechSynthesizer
            let convertedBuffer = AVAudioPCMBuffer(pcmFormat: AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatFloat32, sampleRate: pcmBuffer.format.sampleRate, channels: pcmBuffer.format.channelCount, interleaved: false)!, frameCapacity: pcmBuffer.frameCapacity)!
            do {
                try self.converter!.convert(to: convertedBuffer, from: pcmBuffer)
                self.bufferCounter += 1
                self.player.scheduleBuffer(convertedBuffer, completionCallbackType: .dataPlayedBack, completionHandler: { (type) -> Void in
                    DispatchQueue.main.async {
                        self.bufferCounter -= 1
                        print(self.bufferCounter)
                        if self.bufferCounter == 0 {
                            self.player.stop()
                            self.engine.stop()
                            try! self.audioSession.setActive(false, options: [])
                        }
                    }

                })

                self.converter!.reset()
                //self.player.prepare(withFrameCount: convertedBuffer.frameLength)
            }
            catch let error {
                print(error.localizedDescription)
            }
        }
        activateAudioSession()
        if !self.engine.isRunning {
            try! self.engine.start()
        }
        if !self.player.isPlaying {
            self.player.play()
        }
    }

    func setupAudio(format: AVAudioFormat, globalGain: Float) {
        // QUIRCK: Connecting the equalizer to the engine somehow starts the shared audioSession, and if that audiosession is not configured with .mixWithOthers and if it's not deactivated afterwards, this will stop any background music that was already playing. So first configure the audio session, then setup the engine and then deactivate the session again.
        try? self.audioSession.setCategory(.playback, options: .mixWithOthers)

        eqEffect.globalGain = globalGain
        engine.attach(player)
        engine.attach(eqEffect)
        engine.connect(player, to: eqEffect, format: format)
        engine.connect(eqEffect, to: engine.mainMixerNode, format: format)
        engine.prepare()

        try? self.audioSession.setActive(false)

    }

}
票数 9
EN

Stack Overflow用户

发布于 2019-07-12 11:12:21

文档中提到.volume的默认值是1.0,这是声音最大的。实际响度基于用户音量设置。如果用户把音量调大了,我真的不会觉得声音不够大。

也许你可以考虑在用户音量水平低于某一水平时显示一个视觉警告。似乎this answer通过AVAudioSession展示了如何做到这一点。

AVAudioSession是值得探索的,因为有一些设置确实会影响语音输出...例如,你的应用程序的语音是否会打断来自其他应用程序的音频。

票数 0
EN

Stack Overflow用户

发布于 2020-05-22 18:00:35

试试这个:

代码语言:javascript
复制
import Speech

try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])

let utterance = AVSpeechUtterance(string: "Hello world")        
utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")

let synthesizer = AVSpeechSynthesizer()
synthesizer.speak(utterance)
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56999334

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档