steep-balloon-41261
06/05/2023, 9:26 PMbillions-summer-21168
06/05/2023, 9:26 PMbillions-summer-21168
06/05/2023, 11:21 PMmagnificent-art-43333
06/06/2023, 2:54 AMdry-elephant-14928
06/06/2023, 7:34 AMbillions-summer-21168
06/06/2023, 1:28 PMeager-zoo-16408
06/06/2023, 3:01 PM<RoomAudioRenderer />
(https://github.com/livekit/components-js/blob/main/packages/react/src/components/RoomAudioRenderer.tsx) component to render the audio or have you implemented something custom at the participant level?eager-zoo-16408
06/06/2023, 3:03 PMVideoConference
component:
https://github.com/livekit/components-js/blob/7f7ddfb27f835ec6cf8d720d7c4f1d431770567a/packages/react/src/prefabs/VideoConference.tsx#L112-L116billions-summer-21168
06/06/2023, 4:08 PMRoomAudioRenderer
. I actually am not using the VideoConference
component at all and have replaced it with something custom, but that custom piece is missing the RoomAudioRenderer
Is there anything else I need to do besides drop that component in to my custom VideoConference
replacement? I just dropped it in but I'm still not getting audioeager-zoo-16408
06/06/2023, 4:16 PMRoomAudioRenderer
as a child of the LiveKitRoom
component.
Do you get any error message in the console?
Can you share some code to show what your implementation looks like?billions-summer-21168
06/06/2023, 4:23 PMRoomAudioRenderer
, which says could not playback audio DOMException: The play() request was interrupted by a new load request
billions-summer-21168
06/06/2023, 4:30 PMbillions-summer-21168
06/06/2023, 4:31 PMLiveKitRoom
and within it, our custom component called SessionLayout
which replaces the VideoConference
<LiveKitRoom
room={room}
token={token}
serverUrl={process.env.NEXT_PUBLIC_LIVEKIT_SERVER_URL}
connect={true}
video={true}
audio={true}
data-lk-theme="default"
style={{ backgroundColor: 'transparent' }}
onConnected={() => setConnected(true)}
onDisconnected={() => {
router.replace('/join')
}}
>
{connected && (
<SessionLayout
cameraControlEnabled={cameraControlEnabled}
microphoneControlEnabled={microphoneControlEnabled}
selfViewVisible={selfViewVisible}
endCallEnabled={endCallEnabled}
canvasVisible={canvasVisible}
/>
)}
</LiveKitRoom>
billions-summer-21168
06/06/2023, 4:34 PMSessionLayout
was copied from VideoConference
so a lot of it should look similar but with some functional and UI tweaks we wanted to make. I added RoomAudioRenderer
to the end of this component.
export default function SessionLayout({
cameraControlEnabled,
microphoneControlEnabled,
selfViewVisible,
endCallEnabled,
canvasVisible,
}: SessionLayoutProps) {
const participantIdentities = useParticipants().map((p) => p.identity)
const roomName = useRoomContext().name
const tracks = filterLocalTrack(
useTracks(
[
{ source: Track.Source.Camera, withPlaceholder: true },
{ source: Track.Source.ScreenShare, withPlaceholder: false },
],
{ updateOnlyOn: [RoomEvent.ActiveSpeakersChanged] }
),
selfViewVisible
)
const screenShareTracks = tracks
.filter(isTrackReference)
.filter((track) => track.publication.source === Track.Source.ScreenShare)
const layoutContext = useCreateLayoutContext()
const focusTrack = filterLocalTrack(
usePinnedTracks(layoutContext),
selfViewVisible
)?.[0]
const carouselTracks = tracks.filter(
(track) => !isEqualTrackRef(track, focusTrack)
)
const [showControlPanel, setShowControlPanel] = useState(false)
const [widgetState, setWidgetState] = useState<WidgetState>({
showChat: false,
})
const [clipboardOpen, setClipboardOpen] = useState(false)
const userContext = useUser()
useEffect(() => {
// if screen share tracks are published, and no pin is set explicitly, auto set the screen share
if (
screenShareTracks.length > 0 &&
focusTrack === undefined &&
!canvasVisible
) {
layoutContext.pin.dispatch?.({
msg: 'set_pin',
trackReference: screenShareTracks[0],
})
} else if (
(screenShareTracks.length === 0 &&
focusTrack?.source === Track.Source.ScreenShare) ||
tracks.length <= 1 ||
canvasVisible
) {
layoutContext.pin.dispatch?.({ msg: 'clear_pin' })
}
}, [
JSON.stringify(screenShareTracks.map((ref) => ref.publication.trackSid)),
tracks.length,
focusTrack?.publication?.trackSid,
canvasVisible,
])
const copyUrl = async () => {
try {
await navigator.clipboard.writeText(window.location.href.split('?')[0])
setClipboardOpen(true)
} catch (err) {
console.error('Failed to copy: ', err)
}
}
const widgetUpdate = (state: WidgetState) => {
log.debug('updating widget state', state)
setWidgetState(state)
}
const handleClipboardClose = (
event?: React.SyntheticEvent | Event,
reason?: string
) => {
if (reason === 'clickaway') {
return
}
setClipboardOpen(false)
}
return (
<div className="lk-video-conference">
<LayoutContextProvider
value={layoutContext}
// onPinChange={handleFocusStateChange}
onWidgetChange={widgetUpdate}
>
<div
className="lk-video-conference-inner"
style={{ height: 'calc(100vh - 24px)' }}
>
{!focusTrack && !canvasVisible ? (
<div className="lk-grid-layout-wrapper">
<GridLayout tracks={tracks}>
<ParticipantTile />
</GridLayout>
</div>
) : (
<div className="lk-focus-layout-wrapper">
<FocusLayoutContainer>
<CarouselView tracks={carouselTracks}>
<ParticipantTile />
</CarouselView>
{focusTrack && <FocusLayout track={focusTrack} />}
{canvasVisible && (
<div className="lk-participant-tile">
<Canvas />
</div>
)}
</FocusLayoutContainer>
</div>
)}
<ControlBar
controls={{
chat: true,
microphone: microphoneControlEnabled,
camera: cameraControlEnabled,
leave: endCallEnabled,
}}
>
{userContext.isLoading && <CircularProgress />}
{userContext.user && (
<>
<button
className="lk-button"
style={{ backgroundColor: '#38C9BA' }}
onClick={copyUrl}
>
Copy Join Link
</button>
<button
className="lk-button"
style={{ backgroundColor: '#38C9BA' }}
onClick={() => setShowControlPanel(!showControlPanel)}
>
{`${showControlPanel ? 'Hide' : 'Show'} Control Panel`}
</button>
<button
className="lk-button"
style={{ backgroundColor: '#38C9BA' }}
onClick={() => {
toggleCanvas(participantIdentities, roomName, canvasVisible)
}}
>
{`${canvasVisible ? 'Hide' : 'Show'} Canvas`}
</button>
</>
)}
</ControlBar>
</div>
<Chat style={{ display: widgetState.showChat ? 'flex' : 'none' }} />
{userContext.user && (
<ControlPanel
open={showControlPanel}
togglePanel={setShowControlPanel}
/>
)}
<Snackbar
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
open={clipboardOpen}
autoHideDuration={1500}
onClose={handleClipboardClose}
>
<Alert
onClose={handleClipboardClose}
severity="success"
sx={{ width: '100%' }}
>
Copied Link to clipboard!
</Alert>
</Snackbar>
</LayoutContextProvider>
<RoomAudioRenderer />
</div>
)
}
billions-summer-21168
06/06/2023, 5:00 PMeager-zoo-16408
06/06/2023, 5:22 PMSessionLayout
component?
Could you replace your custom SessionLayout
component with the default VideoConference
component to see if the audio works for you?billions-summer-21168
06/06/2023, 5:25 PMcould not playback audio DOMException: The play() request was interrupted by a new load request.
eager-zoo-16408
06/06/2023, 5:28 PMeager-zoo-16408
06/06/2023, 5:32 PMbillions-summer-21168
06/06/2023, 5:34 PMLiveKitRoom
and I still see the same console warning...Do you see anything in this that would lead to a render loop?
import { LiveKitRoom, VideoConference, useToken } from '@livekit/components-react'
import '@livekit/components-styles'
import CircularProgress from '@mui/material/CircularProgress'
import {
Room,
} from 'livekit-client'
import { NextPage } from 'next'
import { useRouter } from 'next/router'
import { useMemo, useState } from 'react'
import { v4 } from 'uuid'
const SessionRoom: NextPage = () => {
const router = useRouter()
const room = new Room()
const { roomId, name } = router.query
const roomName = roomId as string
const displayName = name ? (name as string) : 'User'
const identity = useMemo(() => v4(), [])
const options = {
userInfo: {
identity: identity,
name: displayName,
},
}
const token = useToken('/api/clinician-access-token', roomName, options)
return token ? (
<div>
<LiveKitRoom
room={room}
token={token}
serverUrl={process.env.NEXT_PUBLIC_LIVEKIT_SERVER_URL}
connect={true}
video={false}
audio={true}
data-lk-theme="default"
style={{ backgroundColor: 'transparent' }}
onDisconnected={() => {
router.replace('/join')
}}
>
<VideoConference />
</LiveKitRoom>
</div>
) : (
<div
style={{
width: '100vw',
height: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<CircularProgress />
</div>
)
}
billions-summer-21168
06/06/2023, 5:40 PMCool 🙏. What livekit client version are you using?I was using 1.7.1 for
livekit-client
I just updated to 1.10.0 and I still see the same thing, with the added console warning of volume can only be set on remote audio tracks
billions-summer-21168
06/07/2023, 12:11 AMdry-elephant-14928
06/07/2023, 1:13 AMdry-elephant-14928
06/07/2023, 1:14 AMbillions-summer-21168
06/07/2023, 4:02 AMbillions-summer-21168
06/07/2023, 4:02 AMeager-zoo-16408
06/07/2023, 11:03 AMgit clone git@github.com:livekit/components-js.git
cd components-js
yarn install
Copy and rename the examples/nextjs/.env.example
to examples/nextjs/.env
and update the content with your LiveKit Cloud credentials.
Then run yarn dev:next
, open http://localhost:3000/minimal?user=A in one browser and http://localhost:3000/minimal?user=B in another and see if you still get the same error.billions-summer-21168
06/07/2023, 3:37 PMbillions-summer-21168
06/07/2023, 4:38 PMcould not playback audio DOMException: The play() request was interrupted by a new load request.
• Safari: If I'm using Safari I am getting audio, but I only seem to be getting audio from the second participant that joins. I tested with 3 participants and only the third seemed to be transmitting audio to the other two?
• Firefox: I tested with 3 participants and all three were receiving audio just fine?billions-summer-21168
06/07/2023, 4:38 PMbillions-summer-21168
06/07/2023, 4:40 PMbillions-summer-21168
06/07/2023, 6:22 PMRoomAudioRenderer
and pushing that to production fixed the issue across all the browsers...However it doesn't work locally? These descriptions are still happening locally 🤔eager-zoo-16408
06/08/2023, 10:18 AMStrict Mode enables the following development-only behaviors:
• Your components will re-render an extra time to find bugs caused by impure rendering.
• Your components will re-run Effects an extra time to find bugs caused by missing Effect cleanup.
We need to investigate further to see if we can handle this better from our end. So if you could share a repo with which you can reliably reproduce the bug, we would be very grateful! This could speed up fixing and releasing a new version quite a bit.