<@U084APK40NS> ```async def entrypoint(ctx: JobCon...
# ask-ai
b
@millions-hair-24956
Copy code
async def entrypoint(ctx: JobContext):
    <http://logger.info|logger.info>(f"starting transcriber (speech to text) example, room: {ctx.room.name}")
    # this example uses OpenAI Whisper, but you can use assemblyai, deepgram, google, azure, etc.
    stt_impl = deepgram.STT()

    if not stt_impl.capabilities.streaming:
        # wrap with a stream adapter to use streaming semantics
        stt_impl = stt.StreamAdapter(
            stt=stt_impl,
            vad=silero.VAD.load(
                min_silence_duration=0.2,
            ),
        )
    async def handle_video(track: rtc.Track):
        video_stream = rtc.VideoStream(track)
        async for event in video_stream:
            video_frame = event.frame
            current_type = video_frame.type
            frame_as_bgra = video_frame.convert(rtc.VideoBufferType.BGRA)
            # [...]
        await video_stream.aclose()

    async def transcribe_track(participant: rtc.RemoteParticipant, track: rtc.Track):
        audio_stream = rtc.AudioStream(track)
        stt_forwarder = transcription.STTSegmentsForwarder(
            room=ctx.room, participant=participant, track=track
        )

        stt_stream = stt_impl.stream()
        asyncio.create_task(_forward_transcription(stt_stream, stt_forwarder))

        async for ev in audio_stream:
            stt_stream.push_frame(ev.frame)

    @ctx.room.on("track_subscribed")
    def on_track_subscribed(
        track: rtc.Track,
        publication: rtc.TrackPublication,
        participant: rtc.RemoteParticipant,
    ):
        print(f"track subscribed: {track.sid}, kind: {track.kind}")
        # spin up a task to transcribe each track
        if track.kind == rtc.TrackKind.KIND_AUDIO:
            asyncio.create_task(transcribe_track(track))
        elif track.kind == rtc.TrackKind.KIND_VIDEO:
            asyncio.create_task(handle_video(track))
How do we add screen recording track here and store it in s3? Also give me code for client side changes
g
It seems likely that to add screen recording and store it in S3, you would need to use LiveKit's egress capabilities. This involves setting up a
TrackEgressRequest
to capture the screen recording and specifying S3 as the storage destination. On the client side, you would need to ensure that the screen share track is published to the room. For the server-side, you can initiate a track egress request like this:
Copy code
async def start_track_egress_and_close(lkapi: api.LiveKitAPI, request: api.TrackEgressRequest):
    try:
        egress_info = await lkapi.egress.start_track_egress(request)
        logger.info(f"egress_info: {egress_info}")
    except Exception as e:
        logger.error(f"Error starting track egress: {e}")
    finally:
        await lkapi.aclose()

@ctx.room.on("track_subscribed")
def on_track_subscribed(track: rtc.Track, publication: rtc.TrackPublication, participant: rtc.RemoteParticipant):
    if track.kind == rtc.TrackKind.KIND_VIDEO:
        track_sid = track.sid
        logger.info(f"track_subscribed: {track_sid}")
        request = api.TrackEgressRequest(
            room_name=ctx.room.name,
            track_id=track_sid,
            file=api.DirectFileOutput(
                filepath="{room_name}/{track_id}",
                s3=api.S3Upload(
                    access_key=os.getenv("AWS_ACCESS_KEY_ID"),
                    secret=os.getenv("AWS_SECRET_ACCESS_KEY"),
                    bucket="your-s3-bucket-name",
                ),
            ),
        )
        lkapi = api.LiveKitAPI()
        asyncio.create_task(start_track_egress_and_close(lkapi, request))
For the client-side, you can use the
createScreenShareTracksWithAudio
method to create and publish a screen share track:
Copy code
import 'package:livekit_client/livekit_client.dart';

Future<void> startScreenShare(Room room) async {
  final tracks = await LocalVideoTrack.createScreenShareTracksWithAudio();
  for (var track in tracks) {
    await room.localParticipant.publishTrack(track);
  }
}
Would you like more detailed guidance on any specific part of this process? Sources: - LiveKit Slack Discussion 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.
b
@millions-hair-24956 How do I differentiate b/w screen recording track and video recording track? (
g
To differentiate between a screen recording track and a video recording track in LiveKit, you can use the
TrackSource
property of the track. The
TrackSource
indicates the origin of the media, such as whether it is from a camera or a screen share. According to the LiveKit documentation, a
TrackPublication
object contains a
source
field that specifies the source of the media. This field can have values like
TrackSource.camera
for video from a camera and
TrackSource.screenShareVideo
for screen sharing. Here's a simple way to check the source of a track:
Copy code
def on_track_subscribed(track: rtc.Track, publication: rtc.TrackPublication, participant: rtc.RemoteParticipant):
    if publication.source == TrackSource.screenShareVideo:
        print("This is a screen share track.")
    elif publication.source == TrackSource.camera:
        print("This is a camera video track.")
Would you like more details on how to implement this in your application? Sources: - LiveKit API Primitives 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.
b
@millions-hair-24956 useEffect(() => { if (roomState === ConnectionState.Connected) { localParticipant.setCameraEnabled(config.settings.inputs.camera); localParticipant.setMicrophoneEnabled(config.settings.inputs.mic); localParticipant.setScreenShareEnabled(true); console.log(
Config
+ JSON.stringify(config)); console.log(
Screen Settings
,config.settings.inputs.screen); } }, [config, localParticipant, roomState]); Is this the correct way to ad screen recording? I am not asked permission for screen
g
To enable screen sharing in LiveKit, you should ensure that the
setScreenShareEnabled
method is correctly invoked and that the necessary permissions are requested. The code snippet you provided seems to be on the right track, but there are a few considerations to ensure it works as expected. 1. Permissions: Screen sharing typically requires user permission, which should trigger a browser prompt. If you are not seeing a permission request, ensure that your browser settings allow screen sharing prompts and that your application is correctly configured to request these permissions. 2. Correct Method Usage: The
setScreenShareEnabled
method should be used to start screen sharing. Ensure that this method is correctly implemented and that the
localParticipant
object is properly initialized. 3. Browser Compatibility: Some browsers may have specific requirements or limitations for screen sharing. Make sure you are testing in a supported browser and that any necessary polyfills or configurations are in place. Here's a refined version of your code snippet:
Copy code
useEffect(() => {
  if (roomState === ConnectionState.Connected) {
    localParticipant.setCameraEnabled(config.settings.inputs.camera);
    localParticipant.setMicrophoneEnabled(config.settings.inputs.mic);
    localParticipant.setScreenShareEnabled(true)
      .then(() => {
        console.log('Screen sharing started');
      })
      .catch((error) => {
        console.error('Error starting screen share:', error);
      });
    console.log(`Config: ${JSON.stringify(config)}`);
    console.log('Screen Settings:', config.settings.inputs.screen);
  }
}, [config, localParticipant, roomState]);
If you are still not seeing a permission prompt, you may need to check your browser's console for any errors or warnings that could indicate why the permission request is not being triggered. Would you like more detailed guidance on troubleshooting this issue? Sources: - LiveKit Client SDK JS 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.
b
@millions-hair-24956 It gives me index-69addefe5c531e10.js:1 Error starting screen share: rm: cannot publish track when not connected at ai.<anonymous> (http://localhost:3000/_next/static/chunks/3dbccb2b-9aae2d566ede3894.js:1:285921) at Generator.next (<anonymous>) at a (http://localhost:3000/_next/static/chunks/3dbccb2b-9aae2d566ede3894.js:1:66282) Full code const tracks = useTracks(); useEffect(() => { if (roomState === ConnectionState.Connected) { localParticipant.setCameraEnabled(config.settings.inputs.camera); localParticipant.setMicrophoneEnabled(config.settings.inputs.mic); localParticipant.setScreenShareEnabled(true) .then(() => { console.log('Screen sharing started'); }) .catch((error) => { console.error('Error starting screen share:', error); }); console.log(
Config: ${JSON.stringify(config)}
); console.log('Screen Settings:', config.settings.inputs.screen); } }, [config, localParticipant, roomState]); const agentVideoTrack = tracks.find( (trackRef) => trackRef.publication.kind === Track.Kind.Video && trackRef.participant.isAgent ); const localTracks = tracks.filter( ({ participant }) => participant instanceof LocalParticipant ); const localVideoTrack = localTracks.find( ({ source }) => source === Track.Source.Camera ); const localMicTrack = localTracks.find( ({ source }) => source === Track.Source.Microphone ); const localScreenTrack = localTracks.find( ({ source }) => source === Track.Source.ScreenShare ); console.log(
Local Screen Share tracks: ${localScreenTrack}
); console.log(
Local Tracks: ${JSON.stringify(localTracks)}
)
g
If you're looking for further help, please follow-up on one of the other channels available for community support!