Skip to content

Commit

Permalink
Add controls to RoomAudioRenderer (#648)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ocupe authored Oct 3, 2023
1 parent d794357 commit 2d8cee3
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/quick-crabs-retire.md
Original file line number Diff line number Diff line change
@@ -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`.
11 changes: 10 additions & 1 deletion packages/react/etc/components-react.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export function AudioTrack({ trackRef, onSubscriptionStatusChanged, volume, sour

// @public (undocumented)
export interface AudioTrackProps<T extends HTMLMediaElement = HTMLMediaElement> extends React_2.HTMLAttributes<T> {
// @alpha
muted?: boolean;
// @deprecated (undocumented)
name?: string;
// (undocumented)
Expand Down Expand Up @@ -447,7 +449,14 @@ export interface PreJoinProps extends Omit<React_2.HTMLAttributes<HTMLDivElement
export { ReceivedChatMessage }

// @public
export function RoomAudioRenderer(): React_2.JSX.Element;
export function RoomAudioRenderer({ volume, muted }: RoomAudioRendererProps): React_2.JSX.Element;

// @public (undocumented)
export interface RoomAudioRendererProps {
// @alpha
muted?: boolean;
volume?: number;
}

// @public (undocumented)
export const RoomContext: React_2.Context<Room | undefined>;
Expand Down
37 changes: 30 additions & 7 deletions packages/react/src/components/RoomAudioRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 (
<div style={{ display: 'none' }}>
{tracks.map((trackRef) => (
<AudioTrack key={getTrackReferenceId(trackRef)} trackRef={trackRef} />
<AudioTrack
key={getTrackReferenceId(trackRef)}
trackRef={trackRef}
volume={volume}
muted={muted}
/>
))}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
31 changes: 27 additions & 4 deletions packages/react/src/components/participant/AudioTrack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<T extends HTMLMediaElement = HTMLMediaElement>
Expand All @@ -20,8 +20,15 @@ export interface AudioTrackProps<T extends HTMLMediaElement = HTMLMediaElement>
/** @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;
}

/**
Expand Down Expand Up @@ -61,7 +68,12 @@ export function AudioTrack({
const mediaEl = React.useRef<HTMLAudioElement>(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,
Expand All @@ -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 <audio ref={mediaEl} {...elementProps} />;
}

0 comments on commit 2d8cee3

Please sign in to comment.