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

如何在Amazon Chime React Native SDK会议开始前配置设备

问题场景

在使用amazon-chime-react-native开发App时,当前只有调用startMeeting后才能获取设备列表,但在设置页面启动会议会直接听到其他参会者的声音,因此NativeFunction.startMeeting必须放在会议页面执行。需要实现先初始化媒体会话(不加入会议)来获取设备列表,再在会议页面正式启动会议的流程。

核心解决方案

Amazon Chime SDK允许在不加入真实会议的情况下初始化媒体模块枚举设备。我们需要在Native层新增初始化临时媒体会话的方法,让设置页面能提前获取设备列表,进入会议前销毁临时会话,再在会议页面正式启动会议并应用用户选择的设备。


1. Android端修改(NativeMobileSDKBridge.kt)

新增临时媒体会话的初始化、销毁方法,并修改设备列表获取逻辑:

// 新增:初始化临时媒体会话(仅用于设备枚举,不连接真实会议)
fun initializeMediaSession() {
    val meetingConfiguration = MeetingConfiguration()
    val audioVideoConfiguration = AudioVideoConfiguration().apply {
        enableAudio = true
        enableVideo = true
    }
    meetingConfiguration.audioVideoConfiguration = audioVideoConfiguration

    // 使用空凭证创建临时会话配置
    val meetingSessionConfiguration = MeetingSessionConfiguration(
        MeetingCredentials("", "", ""),
        meetingConfiguration
    )
    meetingSession = DefaultMeetingSession(
        meetingSessionConfiguration,
        ConsoleLogger(Level.INFO),
        applicationContext
    )

    // 启动音频模块以枚举设备
    meetingSession?.audioVideo?.start()
}

// 修改:确保未初始化会话时也能返回设备列表
fun getAudieDevicesList(): WritableMap{
    meetingSession ?: initializeMediaSession()
    
    val listAudioDevices = meetingSession?.audioVideo?.listAudioDevices()
    val map: WritableMap = WritableNativeMap()
    val list: WritableArray = WritableNativeArray()

    listAudioDevices?.forEach {
        val device: WritableMap = WritableNativeMap().apply {
            putString("id", it.id)
            putString("label", it.label)
            putString("type", it.type.name)
        }
        list.pushMap(device)
    }
    map.putArray("devices", list)
    return map
}

// 新增:销毁临时媒体会话
fun destroyMediaSession() {
    meetingSession?.audioVideo?.stop()
    meetingSession = null
}

2. iOS端修改(NativeMobileSDKBridge.m)

新增对应方法并调整设备列表获取逻辑:

// 新增:初始化临时媒体会话
RCT_EXPORT_METHOD(initializeMediaSession)
{
    MeetingConfiguration *meetingConfig = [[MeetingConfiguration alloc] init];
    AudioVideoConfiguration *avConfig = [[AudioVideoConfiguration alloc] init];
    avConfig.enableAudio = YES;
    avConfig.enableVideo = YES;
    meetingConfig.audioVideoConfiguration = avConfig;

    // 创建空凭证的临时会话配置
    MeetingCredentials *credentials = [[MeetingCredentials alloc] initWithMeetingId:@"" attendeeId:@"" externalUserId:@""];
    MeetingSessionConfiguration *sessionConfig = [[MeetingSessionConfiguration alloc] initWithMeetingCredentials:credentials configuration:meetingConfig];

    meetingSession = [[DefaultMeetingSession alloc] initWithConfiguration:sessionConfig logger:[ConsoleLogger loggerWithLogLevel:LogLevelInfo]];
    [meetingSession.audioVideo start];
}

// 修改:自动初始化会话以获取设备列表
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getAudieDevicesList)
{
    if (!meetingSession) {
        [self initializeMediaSession];
    }
    NSArray *deviceList = [meetingSession.audioVideo listAudioDevices];
    NSMutableArray *transformedList = [NSMutableArray array];

    for (MediaDevice * device in deviceList) {
        [transformedList addObject:@{
            @"label": device.label ?: @"Unknown",
            @"type": [NSString stringWithFormat:@"%i", device.type],
            @"id": device.id ?: @""
        }];
    }

    return @{@"devices":transformedList};
}

// 新增:销毁临时媒体会话
RCT_EXPORT_METHOD(destroyMediaSession)
{
    [meetingSession.audioVideo stop];
    meetingSession = nil;
}

3. React Native层修改(Bridge.ts)

在NativeFunction中新增初始化、销毁临时会话的方法:

export const NativeFunction = {
  // 新增临时会话操作方法
  initializeMediaSession: NativeModules.NativeMobileSDKBridge.initializeMediaSession,
  destroyMediaSession: NativeModules.NativeMobileSDKBridge.destroyMediaSession,
  // 原有方法保留
  startMeeting: NativeModules.NativeMobileSDKBridge.startMeeting,
  stopMeeting: NativeModules.NativeMobileSDKBridge.stopMeeting,
  setMute: NativeModules.NativeMobileSDKBridge.setMute,
  setAudioDevice: NativeModules.NativeMobileSDKBridge.setAudioDevice,
  getAudioDevicesList: NativeModules.NativeMobileSDKBridge.getAudieDevicesList,
  setCameraOn: NativeModules.NativeMobileSDKBridge.setCameraOn,
  bindVideoView: NativeModules.NativeMobileSDKBridge.bindVideoView,
  unbindVideoView: NativeModules.NativeMobileSDKBridge.unbindVideoView,
  switchCamera: NativeModules.NativeMobileSDKBridge.switchCamera,
  sendDataMessage: NativeModules.NativeMobileSDKBridge.sendDataMessage,
};

4. 设备设置页面修改(DeviceSetup.tsx)

调整设备获取逻辑,离开时销毁临时会话并传递选中设备参数:

const DeviceSetup: FC<Props> = ({ route }) => {
  const navigation = useNavigation();

  const [microphones, setMicrophones] = useState([]);
  const [selectedMicrophone, setSelectedMicrophone] = useState();
  const [speakers, setSpeakers] = useState([]);
  const [selectedSpeaker, setSelectedSpeaker] = useState();

  const handleJoinToCall = useCallback(
    async () => {
      // 销毁临时会话后进入会议页面
      await NativeFunction.destroyMediaSession();
      navigation.dispatch(
        CommonActions.reset({
          index: 1,
          routes: [
            {
              name: PATHS.CALL,
              params: { ...route.params, selectedMicrophone, selectedSpeaker },
            },
          ],
        })
      );
    },
    [selectedMicrophone, selectedSpeaker]
  );

  const refreshDevices = useCallback(async () => {
    // 初始化临时会话后获取设备列表
    await NativeFunction.initializeMediaSession();
    const deviceList = await NativeFunction.getAudioDevicesList();

    const microphonesList = deviceList?.devices.filter(
      (x: AudioDevice) => x.type === 'AUDIO_HANDSET' || x.type === '3'
    );
    const speakersList = deviceList?.devices.filter(
      (x: AudioDevice) => x.type === 'AUDIO_BUILTIN_SPEAKER' || x.type === '2'
    );
    setMicrophones(microphonesList || []);
    setSelectedMicrophone(microphonesList?.[0]);
    setSpeakers(speakersList || []);
    setSelectedSpeaker(speakersList?.[0]);
  }, []);

  // 原有requestPermissions、onDeviceChange逻辑保留不变

  useEffect(() => {
    requestPermissions();
    // 组件卸载时自动销毁临时会话
    return () => {
      NativeFunction.destroyMediaSession();
    };
  }, []);

  // 原有UI代码保留不变
};

export default DeviceSetup;

5. 会议页面修改(Call.tsx)

正式启动会议并应用用户选中的设备:

const Call: FC<Props> = ({ route }) => {
  const { selectedMicrophone, selectedSpeaker, meetingId, userName } = route.params;

  useEffect(() => {
    const startMeeting = async () => {
      // 正式启动会议
      await NativeFunction.startMeeting(meetingId, userName);
      // 应用用户选择的音频设备
      if (selectedMicrophone) {
        await NativeFunction.setAudioDevice(selectedMicrophone.id);
      }
      if (selectedSpeaker) {
        await NativeFunction.setAudioDevice(selectedSpeaker.id);
      }
    };

    startMeeting();

    return () => {
      NativeFunction.stopMeeting();
    };
  }, []);

  // 会议页面其他逻辑保留不变
};

export default Call;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:25:08