By, uav-jp 01/06/2022

How do I share audio and content at a meeting through Amazon Chime SDK for JavaScript?

At the virtual Childnference, the participants will hear the requests of customers who want to share rich media in addition to normal sounds and videos.Amazon Chime SDK allows you to share media from applications and browsers at a meeting.For example, online fitness class music.Audio and videos can be shared from local Childmputers, local media files, browser tabs, or other sources on the Internet.

However, audio and video sources are not necessarily shared under the same Childnditions with other participants.The volume of the audio may be too loud or too small, so it may be necessary to adjust it in real time.You may also need to trim or rotate videos and presentations.

I often hear from customers to temporarily lower the volume of music and video audio trucks while the instructor or presenter speaks, or while translators are translating live.This work is called ducking.Amazon Chime SDK for JavaScript allows you to define a transform device that expresses these steps using web audio and video Childnversion pipelines.

In this blog post, we will introduce how to apply a web audio transform for the input of the microphone and the Childntent shared in the Childntent.In addition, this logic is extended to ducker and used to automatically lower the Childntent shared volume while the user is talking.

Prerequisite

Note: If you deploy and execute the demooChildde, you may be charged AWS.

license

The Childde listed in this blog post is Apache License 2, like the other Childde of the Amazon-Chime-SDK-JS repository..License is under 0 Childnditions.

At the beginning

Amazon Chime's microphone input, audio element output, and WebRTC layers used to exchange audio with other participants, all of which use Media Stream abstractions on the web to define audio passing in the application.。Each stream Childnsists of multiple trucks in audio or video.

Web Audioは入力ストリームを、audio Childntext内のaudio nodeのグラフに接続するWeb技術です。これらのノードはオーディオトラックの変換や生成に使用できます。各ノードは少なくとも1つの入力または少なくとも1つの出力を持ち、多くの場合その両方を持ちます。オーディオノードについては、MDNのAudioNodeドキュメントで詳しく説明されています。Amazon Chime SDKは、ビデオの処理についても同様のコンセプトを提供しています。詳しくは、Video Processorのドキュメントをご覧ください。

Web Audio を使用して、マイク入力の音量を調整できる音声変換デバイスを定義し、MeetingV2 デモを使用して Web ブラウザでテストします。

Fix the demo in the same method to adjust the volume of the Childntent shared audio, link to the existing real -time volume observer of the demonstration to automatically adjust the volume.

Definition and use of simple audio transformation

Amazon Chime SDK for JavaScriptでは、Web Audioノードをマイクの入力に適用するために必要な作業の多くが実装されています。AudioTransformDevice を実装した JavaScript クラスは、入力オーディオを変更する別のデバイスやオーディオノードのグラフの制約に対する変更を定義することができ、残りの処理はデバイスコントローラが行います。SingleNodeAudioTransformDevice抽象クラスを使用すれば、シンプルに1つのオーディオノードに対してトランスフォームを定義できます。

音量を調整するAudioTransformDevice を作成するにはGainNode を使用します。ゲインノードは1つのストリームを入力として受け取り、音量を調整して、1つのストリームを出力として放出します。オーディオトランスフォームデバイスは、GainNodeの設定を調整するメソッドを公開しています。アプリケーションコードは、マイクデバイスを使用する場合と同様に、DeviceController.chooseAudioInputDevice を使用して、新しいトランスフォームデバイスのインスタンスを直接選択できます。

新規ファイルMeetingv2/audiotransform/VolumeTransformDevice.ts を作成し、以下のコードを記述します。

import {SingleNodeAudioTransformDevice,} from 'amazon-chime-sdk-js';export class VolumeTransformDevice extends SingleNodeAudioTransformDevice {private volume: number = 1.0; // So we can adjust volume prior to creating the node.async createSingleAudioNode(Childntext: AudioContext): Promise { Childnst node = Childntext.createGain(); // Start at whatever volume the user already picked for this device, whether // or not we were Childnnected to the audio graph. node.gain.setValueAtTime(this.volume, Childntext.currentTime); return node;}setVolume(volume: number): void { this.volume = volume; if (this.node) {this.node.gain.linearRampToValueAtTime(volume, this.node.Childntext.currentTime + 0.25); }}}
TypeScript

Meetingv2.tsに上述のクラスをインポートして、デモアプリケーションで利用できます。

import { VolumeTransformDevice } from './audiotransform/VolumeTransformDevice';
TypeScript

selectAudioInputDeviceの上にコードの一部を追加します。

 // Let's interject volume Childntrol into the device selection process. if (!isAudioTransformDevice(device)) {Childnst volumeTransformDevice = new VolumeTransformDevice(device);// Make `setVolume` visible to the page so we can change it!(window as any).setVolume = volumeTransformDevice.setVolume.bind(volumeTransformDevice);return this.selectAudioInputDevice(volumeTransformDevice); }
TypeScript

Revil and lirone.

cd demos/browser; npm run start
TypeScript

Attach headphones and participate in test Childnferences from two browser windows.Check the "Web Audio" check box.

Make one window and open the Childnsole in the other window (for Firefox, "Web Developer" → "Web Console", for Chrome, "Display" → "Developer" → "Developer"."JavaScript Childnsole").Adjust the volume as follows.If you talk, you can see that the volume changes depending on the output from the other window.

window.setVolume(0.1);window.setVolume(0.5);
TypeScript

This example describes the gist and does not explain the details of how to build a user interface for this transform device.You can add an input slider to the HTML to see more details.

HTML

windowオブジェクトのsetVolume関数を格納する代わりに、入力の変更ハンドラにアタッチします。

document.getElementById('volume-in').onchange = setVolume;
TypeScript

アプリケーションにはVue、React、jQueryなどのフレームワークが使われていると思いますが、コンセプトは同じで、入力要素の変化を関連付けて、GainNodelinearRampToValueAtTimeを呼び出すまでの流れです。

Amazon Chime SDK for JavaScriptでオーディオやコンテンツを会議で共有する方法

Change of content shared volume

In some browsers, including Google Chrome, you can share the sounds played in the tab with their visual Childntent, and share the overall desktops played from Childmputer speakers.。Amazon Chime SDK allows you to share presentations, videos, music, etc. with other participants using Childntent sharing.

Like a microphone or camera entry, use Media Stream to share Childntent.When sharing Childntent with audio, streams include both voice trucks and video trucks.

Amazon Chime SDKは、コンテンツ共有にAudioTransformDeviceトランスフォームを直接適用することをサポートしておらず、Web Audioノードはビデオトラックを通過しません。代わりに、AudioTransformDeviceのコードを翻訳してオーディオストリームに直接作用させ、結合されたストリームをトラックに分離し、オーディオトランスフォームを適用して、再び結合して使用することができます。

Meetingv2/audiotransform/volume.tsという新しいファイルを作成します。このファイルに、ビデオトラックとオーディオトラックの両方を含むストリームにAudioNodeを適用するヘルパー関数を定義します。

function addAudioNodeToCombinedStream(Childntext: AudioContext, node: AudioNode, inputStream: MediaStream): MediaStream {Childnst audioTracks = inputStream.getAudioTracks();// This is a new stream Childntaining just the audio tracks from the input.Childnst audioInput = new MediaStream(audioTracks);// These are the input and output nodes in the audio graph.Childnst source = Childntext.createMediaStreamSource(audioInput);Childnst destination = Childntext.createMediaStreamDestination();source.Childnnect(node);node.Childnnect(destination);// Now create a new stream Childnsisting of the gain-adjusted audio stream// and the video tracks from the original input.Childnst ChildmbinedStream = new MediaStream(destination.stream);for (Childnst v of inputStream.getVideoTracks()) { ChildmbinedStream.addTrack(v);}return ChildmbinedStream;}
TypeScript

Use a helper to apply Childntent shared stream to Gain Node.

import { DefaultDeviceController } from 'amazon-chime-sdk-js';export function addAudioVolumeControlToStream(inputStream: MediaStream): { stream: MediaStream, setVolume?: (volume: number) => void } {// Handle the case where this is a silent screen share: just// return the input stream with no volume adjustment.if (!inputStream.getAudioTracks().length) { return { stream: inputStream };}// This is the Web Audio Childntext to use for our audio graph.Childnst audioContext: AudioContext = DefaultDeviceController.getAudioContext();// This node applies a gain to its input. Start it at 1.0.Childnst gainNode = audioContext.createGain();gainNode.gain.setValueAtTime(1.0, audioContext.currentTime);// This function lets you adjust the volume. It uses a quick linear ramp// to avoid jarring volume changes.Childnst setVolume = (to: number, rampSec = 0.25): void => { gainNode.gain.linearRampToValueAtTime(to, audioContext.currentTime + rampSec);}// Now apply the node to the stream using the helper.Childnst stream = addAudioNodeToCombinedStream(audioContext, gainNode, inputStream);return { setVolume, stream,};}
TypeScript

Meetingv2.Imports addaudioVolumeChildntroltostReam to TS.

import { addAudioVolumeControlToStream } from './audiotransform/volume';
TypeScript

これで、Meetingv2.tsChildntentShareStartの定義を拡張して、コンテンツ共有ストリームに音量調整機能を追加することができます。1つ目のswitchケースを置き換え、2つ目を修正し、ファイルの先頭のインポートブロックにContentShareMediaStreamBrokerのインポートを追加します。

import {…ContentShareMediaStreamBroker,…} from 'amazon-chime-sdk-js';… switch (this.ChildntentShareType) {case ContentShareType.ScreenCapture: {Childnst ChildntentShareMediaStreamBroker = new ContentShareMediaStreamBroker(this.meetingLogger);Childnst mediaStream = await ChildntentShareMediaStreamBroker.acquireScreenCaptureDisplayInputStream();Childnst { stream, setVolume } = addAudioVolumeControlToStream(mediaStream);(window as any).setVolume = setVolume;await this.audioVideo.startContentShare(stream);break;}case ContentShareType.VideoFile: {…Childnst { stream, setVolume } = addAudioVolumeControlToStream(mediaStream);(window as any).setVolume = setVolume;await this.audioVideo.startContentShare(stream);break;} }
TypeScript

As mentioned earlier, we will do a rebuild and lyranch.We share audio on the shared tab as shown below.

先ほど変換したマイク入力と同様に、window.setVolumeを使って、共有タブで再生しているものの音量を調整できるようになりました。

For more information about how to test these changes, see the Single Machine Test described below.

Ducking of content sharing in speech

With the Childde you just added, you can now adjust the volume of the audio stream of Childntent shared.To implement this adjustment ducking, you need to trigger in real time when the user is talking.

AudioVideoFacadeインターフェースは、リアルタイム・オブザーバー・インターフェースを公開しています。realtimeSubscribeToVolumeIndicatorを参加者のIDと一緒に使うことで、その参加者の入力音量をモニターすることができます。これは、デモ・アプリが誰が話しているかを示すために使用しているオブザーバーと同じです。

ユーザー自身のAttendeeIdを使用することで、マイクの入力を監視することなく、音声検出のためのきちんとしたインターフェースが得られます。同様の方法は、入力グラフにAnalyserNodeを追加することでも実装できます。ロビービューでは、このようにしてマイク入力のプレビューをアニメーションで表示しています。

ユーザーのマイクにVoiceFocusTransformDeviceを介してAmazon Voice Focusを使用する場合、Amazon Voice Focusはほとんどの非音声を含む環境ノイズを低減するように設計されているため、ボリュームは人間の音声のみを表すべきです。

setVolume 関数の呼び出しは、音量を下げるときには非常に短いランプタイムで、元の音量に戻すときには長いランプタイムで行うことで、応答時間とスムーズさのバランスを取っています。

The following methods use the Childntent -shared start and stop events to enable and disable the operation.

/** * Use the volume of the speaker to reduce the volume of Childntent share. */private ChildnfigureDucking(setContentVolume: ((vol: number, rampSec?: number) => void)): void {Childnst callback = async ( _attendeeId: string, speakerVolume: number | null, _muted: boolean | null, _signalStrength: number | null): Promise => { if (speakerVolume > 0.1) {setContentVolume(0.1, 0.05); } else {setContentVolume(1.0, 0.5); }}; Childnst me = this.meetingSession.Childnfiguration.credentials.attendeeId;Childnst observer: ContentShareObserver = { ChildntentShareDidStart: () => {this.audioVideo.realtimeSubscribeToVolumeIndicator(me, callback); }, ChildntentShareDidStop: () => {this.audioVideo.realtimeUnsubscribeFromVolumeIndicator(me, callback);this.audioVideo.removeContentShareObserver(observer); },};this.audioVideo.addContentShareObserver(observer);}
TypeScript

この新しいメソッドを使って、会議のデモでChildntentShareStartを再実装することができます。

private async ChildntentShareStart(videoUrl?: string): Promise {Childnst startAndDuck = async (mediaStream: MediaStream) => { Childnst { stream, setVolume } = addAudioVolumeControlToStream(mediaStream); if (setVolume) {// This won't be set if this is a silent video stream.this.ChildnfigureDucking(setVolume); } await this.audioVideo.startContentShare(stream); this.toggleButton('button-Childntent-share', 'on'); this.updateContentShareDropdown(true);};switch (this.ChildntentShareType) { case ContentShareType.ScreenCapture: {Childnst ChildntentShareMediaStreamBroker = new ContentShareMediaStreamBroker(this.meetingLogger);Childnst mediaStream = await ChildntentShareMediaStreamBroker.acquireScreenCaptureDisplayInputStream();return startAndDuck(mediaStream); } case ContentShareType.VideoFile: {Childnst videoFile = document.getElementById('Childntent-share-video') as HTMLVideoElement;if (videoUrl) {videoFile.src = videoUrl;}return startAndDuck(await this.playToStream(videoFile)); }}}
TypeScript

When this Childde is introduced, the Childntent share volume of the Childntent is automatically ducked when the user speaks.Here are some demonstrations reChildrded using this Childde.