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

如何在Angular项目中集成Amazon Chime SDK?

Angular集成Amazon Chime SDK完整示例

以下是适配Angular的Amazon Chime SDK基础集成示例,包含会议加入/离开、本地/远程视频渲染的核心功能:

1. 安装依赖

在项目根目录执行命令安装SDK包:

npm install amazon-chime-sdk-js

2. 创建会议组件

生成一个chime-meeting组件,替换以下文件内容:

chime-meeting.component.ts

import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
import {
  ConsoleLogger,
  DefaultDeviceController,
  DefaultMeetingSession,
  MeetingSessionConfiguration,
  AudioVideoFacade,
  DeviceChangeObserver,
  MediaDeviceInfo,
} from 'amazon-chime-sdk-js';

@Component({
  selector: 'app-chime-meeting',
  templateUrl: './chime-meeting.component.html',
  styleUrls: ['./chime-meeting.component.css']
})
export class ChimeMeetingComponent implements OnInit, DeviceChangeObserver {
  @ViewChild('localVideo') localVideo!: ElementRef<HTMLVideoElement>;
  @ViewChild('remoteVideo') remoteVideo!: ElementRef<HTMLVideoElement>;

  private meetingSession?: DefaultMeetingSession;
  private audioVideo?: AudioVideoFacade;
  private logger = new ConsoleLogger('ChimeMeeting', 'INFO');

  meetingId = '';
  attendeeId = '';
  region = 'us-east-1';
  isJoined = false;

  ngOnInit(): void {
    // 初始化设备控制器,监听设备变化
    const deviceController = new DefaultDeviceController(this.logger);
    deviceController.addDeviceChangeObserver(this);
  }

  async joinMeeting(): Promise<void> {
    if (!this.meetingId || !this.attendeeId) {
      alert('请填写会议ID和参会者ID');
      return;
    }

    this.isJoined = true;

    // 👇 重要:这里的会议凭证必须从你的后端获取
    // 生产环境绝对不能在前端硬编码,示例仅作占位
    const meetingCredentials = {
      Meeting: {
        MeetingId: this.meetingId,
        MediaPlacement: {
          AudioHostUrl: `wss://signal.chime.aws/control/${this.meetingId}`,
          AudioFallbackUrl: `wss://signal.chime.aws/control/${this.meetingId}`,
          ScreenDataUrl: `wss://signal.chime.aws/control/${this.meetingId}`,
          ScreenSharingUrl: `wss://signal.chime.aws/control/${this.meetingId}`,
          ScreenViewingUrl: `wss://signal.chime.aws/control/${this.meetingId}`,
          SignalingUrl: `wss://signal.chime.aws/control/${this.meetingId}`,
          TurnControlUrl: 'https://ccp.cdn.chime.aws'
        },
        MediaRegion: this.region
      },
      Attendee: {
        AttendeeId: this.attendeeId,
        ExternalUserId: 'angular-participant',
        JoinToken: 'YOUR_JOIN_TOKEN_FROM_BACKEND' // 必须替换为后端生成的有效Token
      }
    };

    try {
      const config = new MeetingSessionConfiguration(
        meetingCredentials.Meeting,
        meetingCredentials.Attendee
      );

      const deviceController = new DefaultDeviceController(this.logger);
      this.meetingSession = new DefaultMeetingSession(config, this.logger, deviceController);
      this.audioVideo = this.meetingSession.audioVideo;

      // 启动本地视频并绑定到DOM元素
      await this.audioVideo.startLocalVideo();
      this.audioVideo.bindVideoElement(this.localVideo.nativeElement);

      // 监听远程视频流,绑定到DOM元素
      this.audioVideo.addVideoTileObserver({
        videoTileDidUpdate: (tile) => {
          if (!tile.localTile && tile.state === 'active') {
            this.audioVideo?.bindVideoElement(tile.tileId, this.remoteVideo.nativeElement);
          }
        }
      });

      // 正式加入会议
      await this.audioVideo.start();
    } catch (err) {
      this.logger.error('加入会议失败:', err);
      this.isJoined = false;
      alert('加入失败,请检查凭证是否有效');
    }
  }

  async leaveMeeting(): Promise<void> {
    if (this.audioVideo) {
      await this.audioVideo.stop();
      this.meetingSession = undefined;
      this.audioVideo = undefined;
      this.isJoined = false;
    }
  }

  // 设备变更监听方法
  audioInputsChanged(devices: MediaDeviceInfo[]): void {
    this.logger.info('音频输入设备更新:', devices);
  }

  audioOutputsChanged(devices: MediaDeviceInfo[]): void {
    this.logger.info('音频输出设备更新:', devices);
  }

  videoInputsChanged(devices: MediaDeviceInfo[]): void {
    this.logger.info('视频输入设备更新:', devices);
  }
}

chime-meeting.component.html

<div class="chime-container">
  <div class="input-group">
    <label>会议ID</label>
    <input type="text" [(ngModel)]="meetingId" placeholder="输入会议ID">
  </div>
  <div class="input-group">
    <label>参会者ID</label>
    <input type="text" [(ngModel)]="attendeeId" placeholder="输入参会者ID">
  </div>
  <div class="input-group">
    <label>AWS区域</label>
    <input type="text" [(ngModel)]="region" value="us-east-1">
  </div>
  <button (click)="joinMeeting()" [disabled]="isJoined">加入会议</button>
  <button (click)="leaveMeeting()" [disabled]="!isJoined">离开会议</button>

  <div class="video-grid">
    <div class="video-card">
      <h4>本地画面</h4>
      <video #localVideo autoplay muted playsinline></video>
    </div>
    <div class="video-card">
      <h4>远程画面</h4>
      <video #remoteVideo autoplay playsinline></video>
    </div>
  </div>
</div>

chime-meeting.component.css

.chime-container {
  max-width: 900px;
  margin: 2rem auto;
  padding: 1.5rem;
  font-family: system-ui, -apple-system, sans-serif;
}

.input-group {
  margin-bottom: 1rem;
}

.input-group label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 500;
}

.input-group input {
  width: 100%;
  padding: 0.75rem;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
}

button {
  padding: 0.75rem 1.5rem;
  margin-right: 1rem;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-weight: 500;
}

button:disabled {
  background-color: #d1d5db;
  cursor: not-allowed;
}

.video-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1.5rem;
  margin-top: 2rem;
}

.video-card {
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 1rem;
}

video {
  width: 100%;
  border-radius: 6px;
  background-color: #f3f4f6;
}

3. 配置App模块

在app.module.ts中导入FormsModule(用于双向绑定)并声明组件:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { ChimeMeetingComponent } from './chime-meeting/chime-meeting.component';

@NgModule({
  declarations: [
    AppComponent,
    ChimeMeetingComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

核心注意事项

  • 凭证安全:示例中的会议凭证是占位内容,生产环境必须通过后端调用Amazon Chime的CreateMeeting和CreateAttendeeAPI生成,绝对不能在前端暴露敏感信息。
  • 浏览器权限:确保应用运行在HTTPS环境(localhost除外),否则浏览器会拒绝授予摄像头/麦克风权限。
  • 错误扩展:示例的错误处理仅作基础提示,实际项目中可以添加更详细的日志、重试逻辑或UI状态提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:20:31