From 2d8cee31904efa2cee24d6467e3fb7bade24ccce Mon Sep 17 00:00:00 2001 From: Jonas Schell Date: Tue, 3 Oct 2023 02:09:15 +0200 Subject: [PATCH] Add controls to RoomAudioRenderer (#648) --- .changeset/quick-crabs-retire.md | 5 +++ packages/react/etc/components-react.api.md | 11 +++++- .../src/components/RoomAudioRenderer.tsx | 37 +++++++++++++++---- packages/react/src/components/index.ts | 2 +- .../src/components/participant/AudioTrack.tsx | 31 ++++++++++++++-- 5 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 .changeset/quick-crabs-retire.md diff --git a/.changeset/quick-crabs-retire.md b/.changeset/quick-crabs-retire.md new file mode 100644 index 000000000..9c466854a --- /dev/null +++ b/.changeset/quick-crabs-retire.md @@ -0,0 +1,5 @@ +--- +"@livekit/components-react": minor +--- + +Add `volume` and `muted` control to `RoomAudioRenderer` and `AudioTrack`. Include to render `Track.Source.Unknown` in `RoomAudioRenderer` as long as they are of king `Track.Kind.Audio`. diff --git a/packages/react/etc/components-react.api.md b/packages/react/etc/components-react.api.md index 235f595a7..a8d5a3c70 100644 --- a/packages/react/etc/components-react.api.md +++ b/packages/react/etc/components-react.api.md @@ -69,6 +69,8 @@ export function AudioTrack({ trackRef, onSubscriptionStatusChanged, volume, sour // @public (undocumented) export interface AudioTrackProps extends React_2.HTMLAttributes { + // @alpha + muted?: boolean; // @deprecated (undocumented) name?: string; // (undocumented) @@ -447,7 +449,14 @@ export interface PreJoinProps extends Omit; diff --git a/packages/react/src/components/RoomAudioRenderer.tsx b/packages/react/src/components/RoomAudioRenderer.tsx index cd3f52fb4..0ccdb81ca 100644 --- a/packages/react/src/components/RoomAudioRenderer.tsx +++ b/packages/react/src/components/RoomAudioRenderer.tsx @@ -5,6 +5,19 @@ import * as React from 'react'; import { useTracks } from '../hooks'; import { AudioTrack } from './participant/AudioTrack'; +/** @public */ +export interface RoomAudioRendererProps { + /** Sets the volume for all audio tracks rendered by this component. By default, the range is between `0.0` and `1.0`. */ + volume?: number; + /** + * If set to `true`, mutes all audio tracks rendered by the component. + * @remarks + * If set to `true`, the server will stop sending audio track data to the client. + * @alpha + */ + muted?: boolean; +} + /** * The `RoomAudioRenderer` component is a drop-in solution for adding audio to your LiveKit app. * It takes care of handling remote participants’ audio tracks and makes sure that microphones and screen share are audible. @@ -17,20 +30,30 @@ import { AudioTrack } from './participant/AudioTrack'; * ``` * @public */ -export function RoomAudioRenderer() { - const tracks = useTracks([Track.Source.Microphone, Track.Source.ScreenShareAudio], { - updateOnlyOn: [], - onlySubscribed: false, - }).filter((ref) => !isLocal(ref.participant)); +export function RoomAudioRenderer({ volume, muted }: RoomAudioRendererProps) { + const tracks = useTracks( + [Track.Source.Microphone, Track.Source.ScreenShareAudio, Track.Source.Unknown], + { + updateOnlyOn: [], + onlySubscribed: false, + }, + ).filter((ref) => !isLocal(ref.participant) && ref.publication.kind === Track.Kind.Audio); React.useEffect(() => { - tracks.forEach((track) => (track.publication as RemoteTrackPublication).setSubscribed(true)); + for (const track of tracks) { + (track.publication as RemoteTrackPublication).setSubscribed(true); + } }, [tracks]); return (
{tracks.map((trackRef) => ( - + ))}
); diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts index 742595470..73139d15b 100644 --- a/packages/react/src/components/index.ts +++ b/packages/react/src/components/index.ts @@ -16,7 +16,7 @@ export * from './participant/VideoTrack'; export * from './participant/ParticipantName'; export * from './participant/TrackMutedIndicator'; export * from './ParticipantLoop'; -export { RoomAudioRenderer } from './RoomAudioRenderer'; +export { RoomAudioRenderer, type RoomAudioRendererProps } from './RoomAudioRenderer'; export * from './RoomName'; export { Toast } from './Toast'; export * from './TrackLoop'; diff --git a/packages/react/src/components/participant/AudioTrack.tsx b/packages/react/src/components/participant/AudioTrack.tsx index c6852f268..570766ee2 100644 --- a/packages/react/src/components/participant/AudioTrack.tsx +++ b/packages/react/src/components/participant/AudioTrack.tsx @@ -4,7 +4,7 @@ import { useMediaTrackBySourceOrName } from '../../hooks/useMediaTrackBySourceOr import type { TrackReference } from '@livekit/components-core'; import { log } from '@livekit/components-core'; import { useEnsureParticipant, useMaybeTrackRefContext } from '../../context'; -import { RemoteAudioTrack } from 'livekit-client'; +import { RemoteAudioTrack, RemoteTrackPublication } from 'livekit-client'; /** @public */ export interface AudioTrackProps @@ -20,8 +20,15 @@ export interface AudioTrackProps /** @deprecated This property will be removed in a future version use `trackRef` instead. */ publication?: TrackPublication; onSubscriptionStatusChanged?: (subscribed: boolean) => void; - /** by the default the range is between 0 and 1 */ + /** Sets the volume of the audio track. By default, the range is between `0.0` and `1.0`. */ volume?: number; + /** + * Mutes the audio track if set to `true`. + * @remarks + * If set to `true`, the server will stop sending audio track data to the client. + * @alpha + */ + muted?: boolean; } /** @@ -61,7 +68,12 @@ export function AudioTrack({ const mediaEl = React.useRef(null); const participant = useEnsureParticipant(_participant); - const { elementProps, isSubscribed, track } = useMediaTrackBySourceOrName( + const { + elementProps, + isSubscribed, + track, + publication: pub, + } = useMediaTrackBySourceOrName( { source: _source, name: _name, participant, publication: _publication }, { element: mediaEl, @@ -80,9 +92,20 @@ export function AudioTrack({ if (track instanceof RemoteAudioTrack) { track.setVolume(volume); } else { - log.warn('volume can only be set on remote audio tracks'); + log.warn('Volume can only be set on remote audio tracks.'); } }, [volume, track]); + React.useEffect(() => { + if (pub === undefined || props.muted === undefined) { + return; + } + if (pub instanceof RemoteTrackPublication) { + pub.setEnabled(!props.muted); + } else { + log.warn('Can only call setEnabled on remote track publications.'); + } + }, [props.muted, pub, track]); + return