How do i record the call and store it to my s3 buc...
# ask-ai
m
How do i record the call and store it to my s3 bucket
t
Thanks for reaching out, Ayush. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
m
this is my code
Copy code
@server.rtc_session(agent_name=AGENT_NAME)
async def handle_job(ctx: JobContext) -> None:
    """
    Entrypoint executed for every job dispatched to voice-agent-ayush.

    Metadata fields injected by dispatcher.py:
        call_id      – database primary key of the Call record
        to           – destination phone number
        human_number – human-readable caller number (optional)
        prompt       – per-call system prompt override (optional)
    """
    # ── Parse dispatch metadata ──────────────────────────────────────────────
    metadata: dict = json.loads(ctx.job.metadata or "{}")

    call_id = metadata.get("call_id")
    to = metadata.get("to")
    human_number = metadata.get("human_number")
    prompt = metadata.get("prompt") or EXAMPLE_PROMPT
    language = metadata.get("language", "English")
    recordingFile = metadata.get("recordingFile") or None
    language_code = LANGUAGE_CODES.get(language, "en")

    <http://logger.info|logger.info>(
        "Job received — call_id=%s  to=%s  human_number=%s",
        call_id,
        to,
        human_number,
    )

    # ── Connect to the LiveKit room ──────────────────────────────────────────
    await ctx.connect()

    # ── Build agent session with STT / LLM / TTS ────────────────────────────
    session = AgentSession(
        stt=deepgram.STT(model="nova-3", language=language_code),
        llm=google.LLM(model="gemini-2.5-flash"),
        tts=deepgram.TTS(model="aura-2-asteria-en"),
        vad=silero.VAD.load(),
    )

    # ── Transcript accumulator ───────────────────────────────────────────────
    transcript_turns: list[str] = []

    await session.start(
        room=ctx.room,
        agent=OutboundAssistant(instructions=prompt),
        room_options=room_io.RoomOptions(
            audio_input=room_io.AudioInputOptions(
                noise_cancellation=lambda params: (
                    noise_cancellation.BVCTelephony()
                    if params.participant.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP
                    else noise_cancellation.BVC()
                ),
            ),
        ),
    )
t
Thanks — I’m responding to your question about recording the call and saving the recording to your S3 bucket, and to the code you pasted (which shows your agent joining a LiveKit room but no recording logic). Short answer: you don’t need to add recording/upload code inside your agent. Configure Auto-Egress on the SIP dispatch rule (room config egress) to automatically record the room and upload the resulting file to your S3 bucket. Your current agent code that connects to the room will work with auto-egress without further changes. Before I give the exact steps and an example request you can use, two quick clarifying questions so I give the right instructions for your setup: • Do you create the SIP dispatch rule programmatically (via the LiveKit API/SDK) or via the LiveKit dashboard? • Do you prefer to provide AWS access_key/secret in the dispatch rule, or will you use an IAM role (AssumeRole) for LiveKit to write to S3? If you want the programmatic example (Python) for creating a SIP dispatch rule with auto-egress to S3, I’ll provide it next. If you use the dashboard or need IAM role instructions instead, tell me which and I’ll tailor the steps. What I’ll provide once you confirm: • A Python example to create a SIP dispatch rule with
room_config.egress
pointing to your S3 bucket (or instructions for the dashboard). • Notes on how to verify recordings (webhook events or dashboard) and where the file will appear in S3. • Security recommendation for using AssumeRole (no long-term keys). Sources: sip | livekit/livekit_composite | DeepWiki | Universal Egress | LiveKit
m
Yeah i dispatch the job progamatiacally
t
Great — since you create the SIP dispatch rule programmatically, here’s a concise, practical Python example and the steps to enable automatic recording (auto‑egress) to your S3 bucket. This uses the LiveKit API pattern shown earlier: create the SIP dispatch rule and set
room_config.egress
to output the room composite to S3. No changes are needed in your agent code — recordings start automatically when the room is active. 1) Example: create a SIP dispatch rule with auto‑egress to S3 (async Python)
Copy code
from livekit import api
import asyncio

async def create_sip_dispatch_rule(lk_url, api_key, api_secret,
                                   trunk_id, s3_bucket, s3_region,
                                   s3_prefix=None, access_key=None, secret=None):
    lk_api = api.LiveKitAPI(url=lk_url, api_key=api_key, api_secret=api_secret)

    # Build S3 upload config; omit access_key/secret if using IAM role (AssumeRole)
    s3_upload = api.S3Upload(
        access_key=access_key,
        secret=secret,
        bucket=s3_bucket,
        region=s3_region,
        prefix=s3_prefix or ""
    )

    encoded_output = api.EncodedFileOutput(
        file_type=api.EncodedFileType.MP4,
        s3=s3_upload
    )

    room_composite = api.AutoEgressConfiguration.RoomComposite(
        file_outputs=[encoded_output]
    )

    egress_cfg = api.AutoEgressConfiguration(room_composite=room_composite)

    room_config = api.RoomConfiguration(egress=egress_cfg)

    dispatch_request = api.CreateSIPDispatchRuleRequest(
        trunk_ids=[trunk_id],
        rule=api.SIPDispatchRule(
            dispatch_rule_individual=api.SIPDispatchRuleIndividual(
                room_prefix="call"  # adjust as needed
            )
        ),
        room_config=room_config
    )

    dispatch_rule = await lk_api.sip.create_sip_dispatch_rule(dispatch_request)
    return dispatch_rule

# Example usage:
# asyncio.run(create_sip_dispatch_rule(
#     lk_url="<https://your-livekit.example.com>",
#     api_key="LK_API_KEY",
#     api_secret="LK_API_SECRET",
#     trunk_id="sip-trunk-123",
#     s3_bucket="your-recordings-bucket",
#     s3_region="us-west-2",
#     s3_prefix="recordings/",
#     access_key="YOUR_AWS_KEY",           # or None if using AssumeRole
#     secret="YOUR_AWS_SECRET"             # or None if using AssumeRole
# ))
2) Where this fits with your agent code • Keep your current agent code that calls
await ctx.connect()
and starts the session — auto‑egress will begin recording the room composite automatically because the dispatch rule’s
room_config.egress
is configured. • No additional recording logic is required inside
handle_job
. 3) Verifying recordings and finding files • After the call ends, LiveKit will upload the composite MP4 to: s3://<your-recordings-bucket>/<prefix>/livekit-room-composite-<timestamp>.mp4 • You can also enable webhooks to receive egress events (e.g.,
egress_started
,
egress_ended
) to confirm when uploads begin and finish. 4) Security recommendations • Prefer using IAM roles (AssumeRole) instead of embedding long‑lived AWS keys: ◦ If you use AssumeRole, omit
access_key
and
secret
in the S3 config and configure the role ARN/external ID on the LiveKit side so LiveKit can assume the role to upload. • If you must supply keys, use a restricted IAM user with write-only permissions to the specific recordings prefix. 5) Optional: monitor via webhooks • Configure webhook handling to capture
egress_started
and
egress_ended
events so you can log the S3 path and status. Use those events to trigger any post-processing. If you’d like, I can: • Provide a sample webhook handler (async Python) to capture egress events. • Show how to configure the dispatch rule to produce per-participant tracks instead of a composite (if you need separate audio tracks). • Help convert the example to your exact SDK version or to sync-style code if you’re not using async. Which of those would be most helpful next?