国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android TTS播報音頻并且配合AudioManager壓低其他音頻聲音

這篇具有很好參考價值的文章主要介紹了Android TTS播報音頻并且配合AudioManager壓低其他音頻聲音。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

使用場景

	1. 攔截三方導(dǎo)航返回的即將播放的文本信息,并且加以處理然后播報語音。
	2. 音頻焦點管理,協(xié)調(diào)與其他音頻的沖突,如后臺播放音樂時導(dǎo)航播報
	3. 提示固定提示音,如超速等滴滴聲音
	4. 控制導(dǎo)航語音音量大小

通過 TTS 播放文本信息

  • 什么是 TTS

TTS 就是 TextToSpeech Google 提供的將文字轉(zhuǎn)換為自然語言流的技術(shù),就是通過接收一段文本,轉(zhuǎn)換為聲音。具體看百度百科

我這使用場景是在第三方返回語音信息時攔截,然后自己經(jīng)過處理后播報出去。具體實現(xiàn)的核心簡化版代碼如下

創(chuàng)建 TTS

	/** Google引擎 */
	const val GOOGLE_TTS_ENGINE = "com.google.android.tts"
    /**
     * 初始化TTS引擎
     */
    private fun createTts() {
    	// contextRef 的弱引用 防止內(nèi)存泄漏
        contextRef.get()?.let { context ->
            tts = if (!isFollowSystem) {
            	// 我們這里項目做的不是國內(nèi)的項目所以如果不跟隨系統(tǒng)選擇的默認的Google引擎
                TextToSpeech(
                        context,
                        { status -> this@TtsManager.onInit(status) },
                        GOOGLE_TTS_ENGINE)
            } else {
            	// 手機默認引擎,這個和手機廠商定制應(yīng)該有關(guān)系 
                TextToSpeech(context) { p0 -> this@TtsManager.onInit(p0) }
            }
            // 設(shè)置語言播報速度
            tts?.setSpeechRate(1f)
            // setOnUtteranceProgressListener 設(shè)置的是語音播報的開始、結(jié)束、異常 等監(jiān)聽事件
            processListenerRef?.get()?.let {
                tts?.setOnUtteranceProgressListener(it)
            }
        }
    }

TextToSpeech 第一個參數(shù)大家都知道,第二個是初始化成功還是失敗的回調(diào),第三個是可以指定引擎,一般手機廠商很多會自己內(nèi)置自己的引擎,默認的話大多應(yīng)該就是 Google 引擎了。this 里面第四個參數(shù)是 packagename 如果本地有其他的引擎可以指定包名,默認null。this 里面第五個參數(shù)是如果指定的引擎失敗會走默認的引擎初始化。

 public TextToSpeech(Context context, OnInitListener listener, String engine) {
        this(context, listener, engine, null, true);
    }

我用的手機不是國行的手機,所以默認是 Google 的 tts 引擎。

下載 TTS

由于目標用戶特性,我這里如果沒有 Google 引擎,會提示下載 Google tts 引擎

  • 先判斷是否有 Google 引擎方法
	fun isInstallGoogleTts():Boolean{
        tts?.engines?.forEach{
            if(it.name ==  "com.google.android.tts") {
                return true
            }
        }
        return false
    }
  • 下載 TTS
private const val GOOGLE_TTS_URI = "market://details?id=com.google.android.tts"
val intent = Intent(Intent.ACTION_VIEW)
            intent.data = Uri.parse(GOOGLE_TTS_URI)
            applicationContext.packageManager?.let {
                if(intent.resolveActivity(it) != null) {
                    startActivity(intent)
                }
            }

TTS 有 Voice 語音包

  • 根據(jù)需要篩選
            tts?.voices?.forEach {
                // 篩選美式英語
                if (it.locale.language == English
                    && (it.locale.country.toUpperCase(Locale.ROOT) == US
                            || it.locale.country.toUpperCase(Locale.ROOT) == UNITED_STATES)) {
                    enVoices.add(it)
                    //刷選美式西班牙語
                } else if (it.locale.language == Spanish
                    && (it.locale.country.toUpperCase(Locale.ROOT) == US
                            || it.locale.country.toUpperCase(Locale.ROOT) == UNITED_STATES)) {
                    spVoices.add(it)
                }
            }

TTS 播放語音

fun speak(text: String, queueModel: Int) {
        Log.d(TAG, "Voice message: $text")
        utteranceId = TAG + messageId++
        // QUEUE_FLUSH interrupts already speaking messages.
        val error: Int = tts?.speak(text, queueModel, null, utteranceId) ?: -1
        if (error != 0) {
            Log.e(TAG, "Error when speaking using Android's TextToSpeech: $error")
        }
}
  • speak 參數(shù)的含義
    public int speak(final CharSequence text,
                     final int queueMode,
                     final Bundle params,
                     final String utteranceId) {
        return runAction((ITextToSpeechService service) -> {
        }, ERROR, "speak");
    }
	@param text :要講的文本字符串,不超過 4000 個字符
	@param queueMode:要使用的隊列策略,主要有兩種
		- public static final int QUEUE_ADD = 1; 隊列模式,在播放隊列的末尾添加新條目。
		- public static final int QUEUE_FLUSH = 0; 主要意思就是前面的刪除留下新的
	@param params:請求參數(shù)可以為null。就是內(nèi)置的一些可配置的引擎參數(shù)。通過 bundle傳入。
	@param utteranceId :此請求的唯一標識符。
	@ return :返回值是代表錯誤嗎 0 成功 , -1 失敗

音頻焦點管理

音頻焦點管理就是解決播報時是否有其他音頻正在播報,比如導(dǎo)航中,后臺放著音樂,前面右轉(zhuǎn)播報時降低音樂音量保證用戶可以聽清楚導(dǎo)航聲音。

通過 android,media 下的 AudioFocusRequest 的音頻焦點管理類和 AudioManager 獲取音頻焦點。核心簡化代碼如下

  • 上面介紹了通過 TTS 播放導(dǎo)航信息播報,則播報之前要獲取到音頻焦點,結(jié)束之后要釋放焦點,否則后臺音樂的音量不會變回去。

  • 首先獲取 AudioFocusRequest

/** audioFocus請求參數(shù)*/
    private var audioRequest: AudioFocusRequest? = null
    private fun createFocusRequest(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            audioRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK)
                .setAudioAttributes(audioAttributes)
                .setOnAudioFocusChangeListener {
                    Log.d(TAG, "init Audio Focus: $it")
                }
                .setAcceptsDelayedFocusGain(false)
                .build()
        }
	}

通過 AudioFocusRequest 的 Builder 來構(gòu)建對象,audioAttributes 設(shè)置一些屬性如下:

    /** audioFocus屬性 */
    private val audioAttributes: AudioAttributes by lazy {
        audioAttr?:AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            .build()
    }
  • setUsage : 設(shè)置用途,因為我這里時導(dǎo)航,所以選擇的 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE 導(dǎo)航用途
    • USAGE_MEDIA:表示音頻的用途是多媒體。
      USAGE_VOICE_COMMUNICATION:表示音頻的用途是語音通信。
      USAGE_NOTIFICATION:表示音頻的用途是通知。
      USAGE_ALARM:表示音頻的用途是鬧鐘。
      USAGE_ASSISTANCE_ACCESSIBILITY:表示音頻的用途是輔助功能和無障礙功能。
  • setContentType: 設(shè)置描述音頻信號(如語音或音樂)的內(nèi)容類型的屬性。以下是其中一些類型
    • CONTENT_TYPE_MUSIC:表示音頻的內(nèi)容類型是音樂。
      CONTENT_TYPE_SPEECH:表示音頻的內(nèi)容類型是語音。
      CONTENT_TYPE_MOVIE:表示音頻的內(nèi)容類型是電影。
      CONTENT_TYPE_SONIFICATION:表示音頻的內(nèi)容類型是提示音或系統(tǒng)聲音。
  • setFlags(int flags):設(shè)置音頻的標志。
  • AudioFocusRequest 的 .setAcceptsDelayedFocusGain(false) 屬性

setAcceptsDelayedFocusGain() 是 AudioAttributes.Builder 類中的一個屬性,用于指示音頻源是否支持延遲獲取焦點(delayed focus gain)。
在 Android 中,當多個應(yīng)用程序同時請求使用音頻焦點時,系統(tǒng)需要決定哪個應(yīng)用程序具有焦點,以便控制音頻的播放和暫停。默認情況下,如果一個應(yīng)用程序請求獲取音頻焦點,系統(tǒng)會立即將焦點轉(zhuǎn)移到該應(yīng)用程序,但在某些情況下,這可能會引起不必要的中斷和干擾。例如,如果用戶正在使用語音助手(例如 Google Assistant)進行語音識別,那么在識別期間可能不希望其他應(yīng)用程序突然播放聲音并中斷語音識別。為了避免這種情況,系統(tǒng)支持延遲獲取焦點,即在請求獲取焦點后,系統(tǒng)會等待一段時間以確定焦點是否真的需要轉(zhuǎn)移,如果不需要,則會保留焦點。
如果一個應(yīng)用程序支持延遲獲取焦點,那么當它請求獲取焦點時,系統(tǒng)會通知它是否已經(jīng)獲得了焦點,并告訴它何時將焦點轉(zhuǎn)移到該應(yīng)用程序。這使得應(yīng)用程序可以在等待焦點時繼續(xù)播放音頻,而不必擔心在焦點轉(zhuǎn)移時被中斷。
因此,setAcceptsDelayedFocusGain() 屬性的意義是指示音頻源是否支持延遲獲取焦點。如果一個音頻源支持延遲獲取焦點,那么應(yīng)該將該屬性設(shè)置為 true,否則應(yīng)該將其設(shè)置為 false。如果不確定是否需要支持延遲獲取焦點,則可以使用默認值 false。

我這里因為要求實時性延遲的話會很危險,所以設(shè)置成了 false

  • 下一步獲取 AudioManager
    private val audioManager: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager

請求音頻焦點

  • 我這里時在 TTS 開始播報之謙時候獲取焦點,播放結(jié)束或者中斷的時候移除,TTS回調(diào)如下:
private val utteranceProgressListener = object : UtteranceProgressListener() {
        override fun onStart(utteranceId: String?) {
        	// 獲取焦點
            audioFocusManager.requestAudioFocus()
            // 根據(jù)配置選擇是否增加音量
            increaseVolume()
        }

        override fun onDone(utteranceId: String?) {
        	// 釋放焦點
            audioFocusManager.abandonAudioFocus()
            // 還原音量
            recoverVolume()
        }

        @Deprecated("Deprecated in Java")
        override fun onError(utteranceId: String?) {
        }

        override fun onError(utteranceId: String?, errorCode: Int) {
            super.onError(utteranceId, errorCode)
            // 釋放焦點
            audioFocusManager.abandonAudioFocus()
             // 還原音量
            recoverVolume()
        }

        override fun onStop(utteranceId: String?, interrupted: Boolean) {
            super.onStop(utteranceId, interrupted)
            //1.使用speak的QUEUE_FLUSH模式,打斷上一個,上一個不會回調(diào)onDone,但是會回調(diào)onStop
            //2.直接stop也會回調(diào)onStop
            audioFocusManager.abandonAudioFocus()
             // 還原音量
            recoverVolume()
        }
    }
/**
     * 請求音頻焦點,通過 audioManager 喝 audioFocusRequest來請求焦點
     *
     * @return 音頻焦點請求結(jié)果
     */
    fun requestAudioFocus(): Int {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                audioRequest?.let {
                    return audioManager.requestAudioFocus(it)
                }
                return AudioManager.AUDIOFOCUS_REQUEST_FAILED
            } else {
            	// 這個已經(jīng)棄用
                return audioManager.requestAudioFocus(
                    {
                        Log.d(TAG, "requestAudioFocus Audio Focus: $it")
                    },
                    AudioManager.STREAM_ACCESSIBILITY,
                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
                )
            }
        } catch (e: IllegalArgumentException) {
            e.printStackTrace()
        }
        return AudioManager.AUDIOFOCUS_REQUEST_FAILED
    }

釋放焦點

    /**
     * 釋放audio焦點
     */
    fun abandonAudioFocus() {
        audioRequest?.let {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                audioManager.abandonAudioFocusRequest(it)
            } else {
            	// 棄用的方法
                audioManager.abandonAudioFocus{
                    Log.d(TAG, "abandonAudioFocus Audio Focus: $it")
                }
            }
        }
    }

通過 AudioManager 增加或者減少音量

    private fun increaseVolume() {
    	// 判斷用戶開關(guān)是否開啟
        if (isVolumeUp()) {
            //記錄原始音量
            recordOriginVolume = getVolume()
            //靜音情況下直接返回
            if (recordOriginVolume <= 0) {
                return
            }
            // 設(shè)置音量,固定增加量,我們這里增加了原來的百分之三十
            setVolume(recordOriginVolume + increaseVolumeNum)
            //記錄修改后的音量
            recordTargetVolume = getVolume()
            isVolumeUpping = true
        }
    }
  • 獲取當前系統(tǒng)設(shè)置音量
    private fun getVolume(): Int {
        return try {
            audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
        } catch (e: Exception) {
            TPLogUtils.e(TAG, "getVolume() error : message:${e.message}")
            0
        }
    }

audioManager 的 getStreamVolume() 的類型有以下幾種可以根據(jù)需求選擇

STREAM_VOICE_CALL:語音通話音頻流。
STREAM_SYSTEM:系統(tǒng)提示音和聲音效果音頻流。
STREAM_RING:電話鈴聲音頻流。
STREAM_NOTIFICATION:通知提示音和通知音效音頻流。
STREAM_ALARM:鬧鐘提示音頻流。
STREAM_DTMF:撥號按鍵音頻流。
STREAM_ACCESSIBILITY:輔助功能音頻流
  • setVolume 設(shè)置音量
    private fun setVolume(volumeIndex: Int, flags: Int = 0) {
        try {
            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volumeIndex, flags)
        } catch (e: Exception) {
            TPLogUtils.e(
                TAG,
                "setVolume() error : message:${e.message},volumeIndex:$volumeIndex,flags:$flags"
            )
        }
    }

音量設(shè)置完成,播放完成以后記得設(shè)置回原來的值,以免越來越大。

AudioManager 常用的 API

  • AudioManager 類的一些常用 API:
setStreamVolume(int streamType, int index, int flags):設(shè)置指定流類型(streamType)的音量值(index),其中標志(flags)通常設(shè)置為 0。
getStreamVolume(int streamType):獲取指定流類型(streamType)的當前音量值。
setMode(int mode):設(shè)置音頻模式(mode),例如音樂播放或電話通話。
setSpeakerphoneOn(boolean on):設(shè)置是否使用揚聲器(speakerphone)進行音頻輸出。
isSpeakerphoneOn():檢查當前是否使用揚聲器(speakerphone)進行音頻輸出。
setMicrophoneMute(boolean on):設(shè)置麥克風(fēng)靜音狀態(tài)。
isMicrophoneMute():檢查當前麥克風(fēng)是否處于靜音狀態(tài)。
setWiredHeadsetOn(boolean on):設(shè)置是否插入有線耳機。
isWiredHeadsetOn():檢查當前是否插入有線耳機。
setBluetoothScoOn(boolean on):設(shè)置是否使用藍牙 SCO 音頻通道。
startBluetoothSco():開始使用藍牙 SCO 音頻通道。
stopBluetoothSco():停止使用藍牙 SCO 音頻通道。
isBluetoothScoOn():檢查當前是否使用藍牙 SCO 音頻通道。
setBluetoothScoHeadset(AudioDevice bluetoothScoHeadset):設(shè)置當前藍牙耳機設(shè)備。
isBluetoothScoAvailableOffCall():檢查當前是否支持在非通話狀態(tài)下使用藍牙 SCO 音頻通道。

通過這些 API ,可以滿足大多數(shù)場景下的語音播報需求。文章來源地址http://www.zghlxwxcb.cn/news/detail-672857.html

到了這里,關(guān)于Android TTS播報音頻并且配合AudioManager壓低其他音頻聲音的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【TTS】uni-app語音播報app開發(fā) / MT-TTS安卓原生自帶語音合成插件(免費無限次)

    【TTS】uni-app語音播報app開發(fā) / MT-TTS安卓原生自帶語音合成插件(免費無限次)

    TTS 是 Text To Speech 的縮寫,即“ 從文本到語音 ”,是人機對話的一部分,讓機器能夠說話。TTS是語音合成應(yīng)用的一種。 在程序開發(fā)中,有很多TTS的插件,比如百度,訊飛,等等,但是大部分產(chǎn)品都不是完全免費無限制次數(shù)調(diào)用的且需在線使用 本篇文章介紹一種免費快捷且可

    2023年04月15日
    瀏覽(85)
  • 【ESP32S3 Sense接入語音識別+MiniMax模型+TTS模塊語音播報】

    【ESP32S3 Sense接入語音識別+MiniMax模型+TTS模塊語音播報】

    講解視頻: ESP32S3 AI助手使用MiniMax大模型生產(chǎn)工具1 大家好,今天的教程將圍繞如何實現(xiàn)精準的語音播報功能展開,我們用到了ESP32S3 Sense接入語音識別+MiniMax模型對話+SNR9816TTS模塊。 目前這是我使用的ESP32S3官方硬件??????(小小的身材有大大的力量)只需要35元加攝像頭麥

    2024年04月12日
    瀏覽(26)
  • Java 音頻播報(內(nèi)置 + 第三方)

    ? ? ? ? jdk內(nèi)置的可以使用,不過呢就是聲音太原始了,這是同過輸入文字然后識別讀出來的。 1、導(dǎo)入JL的依賴 2、代碼實現(xiàn) ? ? ? ? 這個是通過文件播報的,可以在網(wǎng)上下載自己需要的音頻 最近在做項目,做外賣的,其中有一個功能就是接單,商家接單就需要用到這個功

    2024年02月02日
    瀏覽(22)
  • MS-TTS:免費微軟TTS語音合成工具(一鍵合成導(dǎo)出MP3音頻)

    MS-TTS:免費微軟TTS語音合成工具(一鍵合成導(dǎo)出MP3音頻)

    聲明 本工具是個免費工具,遇到問題,還請自行解決,下面有文字教程,B站有視頻教程(鏈接在文章末尾); 其次,微軟接口卡頓,連接超時等問題下方有詳細說明,請仔細看一下; 再次,強制升級是為了統(tǒng)一版本方便問題的收集與解決,如果你能理解最好,不能理解的話

    2024年02月03日
    瀏覽(55)
  • 【專題速遞】音頻生成、TTS和AIGC在音樂上的運用

    ? //?? AIGC的發(fā)展為音頻帶來了什么?AIGC如何賦能音樂創(chuàng)作?如何識別虛假音頻?TTS可以在哪種場景下解決特定問題?7月29日LiveVideoStackCon2023上海站音頻新體驗專場,為您解答。 音頻新體驗 隨著多媒體和通信網(wǎng)絡(luò)技術(shù)的不斷更新,以及新型音視頻應(yīng)用場景的不斷涌現(xiàn),音頻

    2024年02月13日
    瀏覽(18)
  • OpenAI Whisper + FFmpeg + TTS:動態(tài)實現(xiàn)跨語言視頻音頻翻譯

    本文作者系360奇舞團前端開發(fā)工程師 本文介紹了如何結(jié)合 OpenAI Whisper、FFmpeg 和 TTS(Text-to-Speech)技術(shù),以實現(xiàn)將視頻翻譯為其他語言并更換聲音的過程。我們將探討如何使用 OpenAI Whisper 進行語音識別和翻譯,然后使用 FFmpeg 提取視頻音軌和處理視頻,最后使用 TTS 技術(shù)生成新

    2024年02月09日
    瀏覽(16)
  • Unity 工具 之 Azure 微軟SSML語音合成TTS流式獲取音頻數(shù)據(jù)的簡單整理

    Unity 工具 之 Azure 微軟SSML語音合成TTS流式獲取音頻數(shù)據(jù)的簡單整理

    目錄 Unity 工具 之 Azure 微軟SSML語音合成TTS流式獲取音頻數(shù)據(jù)的簡單整理 一、簡單介紹 二、實現(xiàn)原理 三、實現(xiàn)步驟 四、關(guān)鍵代碼 Unity 工具類,自己整理的一些游戲開發(fā)可能用到的模塊,單獨獨立使用,方便游戲開發(fā)。 本節(jié)介紹,這里在使用微軟的Azure 進行語音合成的兩個方

    2024年02月12日
    瀏覽(23)
  • Android文字轉(zhuǎn)語音播報

    Android文字轉(zhuǎn)語音播報

    Android文字轉(zhuǎn)語音播報可以通過Android自帶TTS和第三方語音框架實現(xiàn)。 代碼如下(示例): 代碼如下(示例): 1.包名、應(yīng)用名: com.svox.pico 系統(tǒng)自帶不支持中文語音 com.baidu.duersdk.opensdk 度秘語音引擎3.0 不支持5.0以下系統(tǒng),大小11.95M com.google.android.tts 谷歌文字轉(zhuǎn)語音引擎,不

    2023年04月08日
    瀏覽(26)
  • Unity C# 之 Azure 微軟SSML語音合成TTS流式獲取音頻數(shù)據(jù)以及表情嘴型 Animation 的簡單整理

    Unity C# 之 Azure 微軟SSML語音合成TTS流式獲取音頻數(shù)據(jù)以及表情嘴型 Animation 的簡單整理

    目錄 Unity C# 之 Azure 微軟SSML語音合成TTS流式獲取音頻數(shù)據(jù)以及表情嘴型 Animation 的簡單整理 一、簡單介紹 二、實現(xiàn)原理 三、注意事項 四、實現(xiàn)步驟 五、關(guān)鍵代碼 Unity 工具類,自己整理的一些游戲開發(fā)可能用到的模塊,單獨獨立使用,方便游戲開發(fā)。 本節(jié)介紹,這里在使用

    2024年02月12日
    瀏覽(31)
  • uniapp使用uni.createInnerAudioContext()播放指定音頻并且切換

    uniapp使用uni.createInnerAudioContext()播放指定音頻并且切換

    uniapp API 中 uni.createInnerAudioContext()是無法多音頻播放的 如果我們想同時播放 加上ambient(不中止其他聲音播放,不能后臺播放,靜音后無聲音)這個屬性,我做的這個是用uniapp開發(fā)的一個安卓端的殼包,正常h5用MP3,WMA或者MPEG等格式的音頻都是可以的,但在安卓端手機測試需

    2024年02月11日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包