产品动态
产品近期公告
关于 TRTC Live 正式上线的公告
关于TRTC Conference 正式版上线的公告
Conference 商业化版本即将推出
关于多人音视频 Conference 开启内测公告
关于音视频通话 Call 正式版上线的公告
关于腾讯云音视频终端 SDK 播放升级及新增授权校验的公告
关于 TRTC 应用订阅套餐服务上线的相关说明
AtomicXCore 框架中的 AudioEffectStore 和 DeviceStore 模块,为您的直播应用快速集成音效控制功能,包括麦克风音量、耳返监听,并添加多种趣味变声效果和混响效果。
AudioEffectStore 和 DeviceStore,您将能实现以下核心功能:核心概念 | 类型 | 核心职责与描述 |
class | 代表音效模块的当前状态,通常用于UI渲染。包括变声状态、混响状态、耳返开启状态、耳返音量。所有属性均为 ValueListenable 类型,支持订阅监听。 | |
class | 代表音效模块单例数据管理类。通过它您可以调用修改音效接口,当您调用接口后,相应的 audioEffectState 属性会自动更新,可以通过订阅这个 state 响应式数据来接收和监听状态更新。 | |
class | 代表设备模块的当前状态,通常用于UI渲染。核心属性包括摄像头、麦克风的设备状态、采集音量等。所有属性均为 ValueListenable 类型,支持订阅监听。 | |
class | 代表设备模块单例数据管理类。通过它您可以调用操作摄像头、麦克风接口,当您调用接口后,相应的 state 属性会自动更新,可以通过订阅这个 state 响应式数据来接收和监听状态更新。 |
AudioEffectStore 和 DeviceStore 是单例对象,您可以直接通过 shared 属性在项目的任何位置获取实例。您也可以参考 TUILiveKit 开源 UI demo 项目中的 audio_effect_panel_widget.dart 文件来了解完整的实现逻辑。import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';class _AudioEffectPanelWidgetState {final _audioEffectStore = AudioEffectStore.shared;final _deviceStore = DeviceStore.shared;}
Switch 控件实现开关耳返功能。Slider 控件实现左右拖动滑块来调节音量的功能,并将 Slider 的值映射成音量值,调用 setVoiceEarMonitorVolume(volume)。请注意,该接口接收的参数范围是 [0, 150],所以您需要将 UI 控件的值(例如 Slider 的 0.0 - 1.0)映射到 0 - 150 的范围。import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';/// 耳返控制组件class EarMonitorWidget extends StatelessWidget {const EarMonitorWidget({super.key});@overrideWidget build(BuildContext context) {final audioEffectStore = AudioEffectStore.shared;return Column(crossAxisAlignment: CrossAxisAlignment.start,children: [// 1. 开关耳返ValueListenableBuilder<bool>(valueListenable: audioEffectStore.audioEffectState.isEarMonitorOpened,builder: (context, isOpened, child) {return SwitchListTile(title: const Text('耳返'),subtitle: const Text('需要插入耳机'),value: isOpened,onChanged: (value) {audioEffectStore.setVoiceEarMonitorEnable(value);},);},),// 2. 调节耳返音量ValueListenableBuilder<int>(valueListenable: audioEffectStore.audioEffectState.earMonitorVolume,builder: (context, volume, child) {return ListTile(title: const Text('耳返音量'),subtitle: Slider(value: volume.toDouble(),min: 0,max: 150,divisions: 150,onChanged: (value) {audioEffectStore.setVoiceEarMonitorVolume(value.toInt());},),trailing: Text('$volume'),);},),],);}}
参数名 | 类型 | 描述 |
enable | bool | 是否开启耳返。 true:开启。 false:关闭。 |
参数名 | 类型 | 描述 |
volume | int | 耳返音量大小。 取值范围:[0, 150] 默认值:100 |
DeviceStore 的 setCaptureVolume(volume) 方法传入音量值即可。Slider 控件实现左右拖动滑块来调节音量的功能,并将 Slider 的值映射成音量值后调用 setCaptureVolume(volume)。请注意,该接口接收的参数范围是 [0, 150],所以您需要将 UI 控件的值(例如 Slider 的 0.0 - 1.0)映射到 0 - 150 的范围。import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';/// 人声音量控制组件class CaptureVolumeWidget extends StatelessWidget {const CaptureVolumeWidget({super.key});@overrideWidget build(BuildContext context) {final deviceStore = DeviceStore.shared;return ValueListenableBuilder<int>(valueListenable: deviceStore.state.captureVolume,builder: (context, volume, child) {return ListTile(title: const Text('人声音量'),subtitle: Slider(value: volume.toDouble(),min: 0,max: 150,divisions: 150,onChanged: (value) {deviceStore.setCaptureVolume(value.toInt());},),trailing: Text('$volume'),);},);}}
参数名 | 类型 | 描述 |
volume | int | 采集音量大小。 取值范围:[0, 150]。 默认值:100。 |
setAudioChangerType(type) 方法,传入相应的 Type 枚举值即可切换效果。import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';/// 变声效果选择组件class VoiceChangerWidget extends StatelessWidget {const VoiceChangerWidget({super.key});@overrideWidget build(BuildContext context) {final audioEffectStore = AudioEffectStore.shared;return Column(crossAxisAlignment: CrossAxisAlignment.start,children: [const Padding(padding: EdgeInsets.all(16),child: Text('变声效果', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),),ValueListenableBuilder<AudioChangerType>(valueListenable: audioEffectStore.audioEffectState.audioChangerType,builder: (context, changerType, child) {return Padding(padding: const EdgeInsets.symmetric(horizontal: 16),child: Wrap(spacing: 8,runSpacing: 8,children: AudioChangerType.values.map((type) {return ChoiceChip(label: Text(_getChangerTypeName(type)),selected: changerType == type,onSelected: (selected) {if (selected) {audioEffectStore.setAudioChangerType(type);}},);}).toList(),),);},),],);}String _getChangerTypeName(AudioChangerType type) {switch (type) {case AudioChangerType.none:return '关闭';case AudioChangerType.child:return '熊孩子';case AudioChangerType.girl:return '萝莉';case AudioChangerType.uncle:return '大叔';case AudioChangerType.ethereal:return '空灵';}}}
参数名 | 类型 | 描述 |
type | 变声效果枚举。 |
setAudioReverbType(type) 方法,传入相应的 Type 枚举值即可切换效果。import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';/// 混响效果选择组件class ReverbWidget extends StatelessWidget {const ReverbWidget({super.key});@overrideWidget build(BuildContext context) {final audioEffectStore = AudioEffectStore.shared;return Column(crossAxisAlignment: CrossAxisAlignment.start,children: [const Padding(padding: EdgeInsets.all(16),child: Text('混响效果', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),),ValueListenableBuilder<AudioReverbType>(valueListenable: audioEffectStore.audioEffectState.audioReverbType,builder: (context, reverbType, child) {return Padding(padding: const EdgeInsets.symmetric(horizontal: 16),child: Wrap(spacing: 8,runSpacing: 8,children: AudioReverbType.values.map((type) {return ChoiceChip(label: Text(_getReverbTypeName(type)),selected: reverbType == type,onSelected: (selected) {if (selected) {audioEffectStore.setAudioReverbType(type);}},);}).toList(),),);},),],);}String _getReverbTypeName(AudioReverbType type) {switch (type) {case AudioReverbType.none:return '关闭';case AudioReverbType.ktv:return 'KTV';case AudioReverbType.room:return '小房间';case AudioReverbType.hall:return '大会堂';case AudioReverbType.deep:return '低沉';case AudioReverbType.loud:return '洪亮';case AudioReverbType.metallic:return '金属声';case AudioReverbType.magnetic:return '磁性';case AudioReverbType.recordingStudio:return '录音棚';}}}
参数名 | 类型 | 描述 |
type | 混响效果枚举。 |
store 的 reset() 方法实现音效重置。store 的 reset() 方法实现音效重置。import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';/// 音效重置组件class AudioEffectResetWidget extends StatelessWidget {const AudioEffectResetWidget({super.key});void _resetAudioEffect() {AudioEffectStore.shared.reset();DeviceStore.shared.reset();}@overrideWidget build(BuildContext context) {return ElevatedButton(onPressed: _resetAudioEffect,child: const Text('重置音效设置'),);}}
import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';/// 音效设置页面class AudioEffectPage extends StatelessWidget {const AudioEffectPage({super.key});@overrideWidget build(BuildContext context) {final audioEffectStore = AudioEffectStore.shared;final deviceStore = DeviceStore.shared;return Scaffold(appBar: AppBar(title: const Text('音效设置')),body: ListView(children: [// 人声音量const Padding(padding: EdgeInsets.all(16),child: Text('人声音量', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),),ValueListenableBuilder<int>(valueListenable: deviceStore.state.captureVolume,builder: (context, volume, child) {return ListTile(title: const Text('采集音量'),subtitle: Slider(value: volume.toDouble(),min: 0,max: 150,divisions: 150,onChanged: (value) {deviceStore.setCaptureVolume(value.toInt());},),trailing: Text('$volume'),);},),const Divider(),// 耳返设置const Padding(padding: EdgeInsets.all(16),child: Text('耳返', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),),ValueListenableBuilder<bool>(valueListenable: audioEffectStore.audioEffectState.isEarMonitorOpened,builder: (context, isOpened, child) {return SwitchListTile(title: const Text('开启耳返'),subtitle: const Text('需要插入耳机'),value: isOpened,onChanged: (value) {audioEffectStore.setVoiceEarMonitorEnable(value);},);},),ValueListenableBuilder<int>(valueListenable: audioEffectStore.audioEffectState.earMonitorVolume,builder: (context, volume, child) {return ListTile(title: const Text('耳返音量'),subtitle: Slider(value: volume.toDouble(),min: 0,max: 150,divisions: 150,onChanged: (value) {audioEffectStore.setVoiceEarMonitorVolume(value.toInt());},),trailing: Text('$volume'),);},),const Divider(),// 变声设置const Padding(padding: EdgeInsets.all(16),child: Text('变声', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),),ValueListenableBuilder<AudioChangerType>(valueListenable: audioEffectStore.audioEffectState.audioChangerType,builder: (context, changerType, child) {return Padding(padding: const EdgeInsets.symmetric(horizontal: 16),child: Wrap(spacing: 8,runSpacing: 8,children: AudioChangerType.values.map((type) {return ChoiceChip(label: Text(_getChangerTypeName(type)),selected: changerType == type,onSelected: (selected) {if (selected) {audioEffectStore.setAudioChangerType(type);}},);}).toList(),),);},),const SizedBox(height: 16),const Divider(),// 混响设置const Padding(padding: EdgeInsets.all(16),child: Text('混响', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),),ValueListenableBuilder<AudioReverbType>(valueListenable: audioEffectStore.audioEffectState.audioReverbType,builder: (context, reverbType, child) {return Padding(padding: const EdgeInsets.symmetric(horizontal: 16),child: Wrap(spacing: 8,runSpacing: 8,children: AudioReverbType.values.map((type) {return ChoiceChip(label: Text(_getReverbTypeName(type)),selected: reverbType == type,onSelected: (selected) {if (selected) {audioEffectStore.setAudioReverbType(type);}},);}).toList(),),);},),const SizedBox(height: 24),// 重置按钮Padding(padding: const EdgeInsets.all(16),child: ElevatedButton(onPressed: () {audioEffectStore.reset();deviceStore.reset();},child: const Text('重置音效设置'),),),],),);}String _getChangerTypeName(AudioChangerType type) {switch (type) {case AudioChangerType.none:return '关闭';case AudioChangerType.child:return '熊孩子';case AudioChangerType.girl:return '萝莉';case AudioChangerType.uncle:return '大叔';case AudioChangerType.ethereal:return '空灵';}}String _getReverbTypeName(AudioReverbType type) {switch (type) {case AudioReverbType.none:return '关闭';case AudioReverbType.ktv:return 'KTV';case AudioReverbType.room:return '小房间';case AudioReverbType.hall:return '大会堂';case AudioReverbType.deep:return '低沉';case AudioReverbType.loud:return '洪亮';case AudioReverbType.metallic:return '金属声';case AudioReverbType.magnetic:return '磁性';case AudioReverbType.recordingStudio:return '录音棚';}}}
AudioEffectStore 和 DeviceStore 的设置是全局生效的,您可以在进入直播间之前或之后随时调用相关接口(例如设置变声、混响或耳返),设置会立即生效并被保留。DeviceStore.shared.setCaptureVolume() 设置。它决定了观众能听到主播的声音大小。AudioEffectStore.shared.setVoiceEarMonitorVolume() 设置。它只决定了主播在耳机里听到的监听声音大小,不会影响观众。AudioEffectStore 和 DeviceStore 是单例,这意味着音效和设备设置是全局生效的,出现这种情况很可能是因为您之前设置过音效但是没有重置,需要在合适的地方调用 reset() 方法重置。DeviceStore 中的麦克风是开启状态(即已调用 openLocalMicrophone())。AudioChangerType 和 AudioReverbType 是可以叠加生效的。例如,您可以同时设置 AudioChangerType.girl 变声和 AudioReverbType.ktv 混响。文档反馈