diff --git a/README.md b/README.md index 96d7ab2..43e8981 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Use this SDK to interact with LiveKit server APIs and create access tokens from your Ruby backend. -This library is designed to work with Ruby 2.6.0 and above. +This library is designed to work with Ruby 3.1 and above. ## Installation @@ -34,6 +34,58 @@ and then `bundle install`. gem install livekit-server-sdk ``` +## Migrating from 0.x to 1.x + +v1.0 is a breaking release. The most important change is behavioral: **service methods now return the response message directly and raise on failure**, instead of returning a `Twirp::ClientResp` that you had to unwrap and error-check yourself. + +### Return values and error handling (breaking) + +In 0.x, every call returned a `Twirp::ClientResp`: you read the result from `.data`, and a failed call came back with a non-nil `.error`. Nothing was raised, so an unchecked failure silently surfaced later as a `nil` result. + +In 1.x, the result is returned directly, and failures raise `LiveKit::ServerError` (or `LiveKit::SipCallError` for SIP dialing calls). + +```ruby +# 0.x — unwrap .data, check .error manually +resp = client.create_room('myroom') +if resp.error + # handle failure +else + room = resp.data +end + +# 1.x — result returned directly, failures raise +begin + room = api.room.create_room('myroom') +rescue LiveKit::ServerError => e + # e.code, e.message, e.metadata +end +``` + +See [Error handling](#error-handling) below for details, including the SIP-specific `LiveKit::SipCallError`. + +### Single entry point (recommended) + +0.x constructed each service client on its own. 1.x adds `LiveKit::LiveKitAPI`, a single entry point that exposes every service (`room`, `egress`, `ingress`, `sip`, `agent_dispatch`, `connector`) over a shared connection. + +```ruby +# 0.x +client = LiveKit::RoomServiceClient.new('https://my.livekit.instance', + api_key: 'yourkey', api_secret: 'yoursecret') +client.list_rooms + +# 1.x +api = LiveKit::LiveKitAPI.new('https://my.livekit.instance', + api_key: 'yourkey', api_secret: 'yoursecret') +api.room.list_rooms +``` + +The individual clients (`LiveKit::RoomServiceClient`, etc.) still exist and take the same arguments, so you can adopt the new error handling first and switch to `LiveKitAPI` later — but note they raise on failure now too. + +### Also new in 1.x + +- **Token authentication** — construct `LiveKitAPI` (or a client) with a pre-signed `token:` instead of an API key/secret, for client-side use where the secret must not be exposed. See [Authentication](#authentication). +- Bug fixes: `start_participant_egress` no longer raises when given a single output; `AgentDispatchServiceClient#get_dispatch` / `#list_dispatch` now return correctly. + ## Usage ### Creating Access Tokens @@ -57,45 +109,81 @@ By default, a token expires after 6 hours. You may override this by passing in ` It's possible to customize the permissions of each participant. See more details at [access tokens guide](https://docs.livekit.io/guides/access-tokens#room-permissions). -### Room Service +### Authentication + +Every request to the server APIs is authenticated. There are two modes: -`RoomServiceClient` is a Twirp-based client that provides management APIs to LiveKit. You can connect it to your LiveKit endpoint. See [service apis](https://docs.livekit.io/guides/server-api) for a list of available APIs. +- **API key & secret** — recommended for backend use. The SDK signs a short-lived token per request from your key and secret. Keep your API secret on the server; never ship it to a client. +- **Access token** — for frontend / client-side use, where the API secret must not be exposed. Pass a pre-signed [access token](https://docs.livekit.io/home/get-started/authentication/) that already carries the grants for the operations you'll perform; the SDK sends it verbatim. + +```ruby +# backend (API key & secret): set LIVEKIT_URL, LIVEKIT_API_KEY, and +# LIVEKIT_API_SECRET, then construct with no arguments... +api = LiveKit::LiveKitAPI.new + +# ...or pass any of them explicitly to override the corresponding env var: +api = LiveKit::LiveKitAPI.new('https://my.livekit.instance', api_key: 'yourkey', api_secret: 'yoursecret') + +# frontend (pre-signed access token): with LIVEKIT_URL set, pass just the token: +api = LiveKit::LiveKitAPI.new(token: 'a-pre-signed-token') +``` + +The url and credentials fall back to the `LIVEKIT_URL`, `LIVEKIT_API_KEY`, `LIVEKIT_API_SECRET`, and `LIVEKIT_TOKEN` environment variables. Values you pass explicitly take precedence; the environment variables are used only as a fallback for arguments you omit — an ambient `LIVEKIT_TOKEN`, for example, won't override an explicitly-provided API key and secret. + +### Server APIs + +`LiveKit::LiveKitAPI` is a single entry point to every server API, exposing each service through a reader: `room`, `egress`, `ingress`, `sip`, `agent_dispatch`, and `connector`. Each method returns the response message directly and raises `LiveKit::ServerError` on failure. See [service apis](https://docs.livekit.io/guides/server-api) for the full list. ```ruby require 'livekit' -client = LiveKit::RoomServiceClient.new('https://my.livekit.instance', +api = LiveKit::LiveKitAPI.new('https://my.livekit.instance', api_key: 'yourkey', api_secret: 'yoursecret') name = 'myroom' -client.list_rooms +room = api.room.create_room(name) + +api.room.list_rooms + +api.room.list_participants(room: name) + +api.room.mute_published_track(room: name, identity: 'participant', + track_sid: 'track-id', muted: true) + +api.room.remove_participant(room: name, identity: 'participant') -client.list_participants(room: name) +api.room.delete_room(room: name) +``` -client.mute_published_track(room: name, identity: 'participant', - track_sid: 'track-id', muted: true) +### Error handling -client.remove_participant(room: name, identity: 'participant') +Failed API calls raise `LiveKit::ServerError`, which exposes the error `code`, message, and any server-provided `metadata`. SIP dialing calls raise `LiveKit::SipCallError` (a `ServerError` subclass) that also exposes the SIP status: -client.delete_room(room: name) +```ruby +begin + api.sip.create_sip_participant('trunk-id', '+15105550100', 'my-room', wait_until_answered: true) +rescue LiveKit::SipCallError => e + puts e # e.g. "SIP call failed: 486 Busy Here (resource_exhausted)" + puts e.sip_status_code # 486 +rescue LiveKit::ServerError => e + puts e.code +end ``` +The per-service clients (`LiveKit::RoomServiceClient`, etc.) can also be constructed individually with the same arguments. + ### Egress Service -`EgressServiceClient` is a ruby client to EgressService. Refer to [docs](https://docs.livekit.io/guides/egress) for more usage examples +Egress is reached via `api.egress`. Refer to [docs](https://docs.livekit.io/guides/egress) for more usage examples. ```ruby require 'livekit' -# starting a room composite to S3 -egressClient = LiveKit::EgressServiceClient.new( - "https://your-url", - api_key: 'key', - api_secret: 'secret' -); +api = LiveKit::LiveKitAPI.new('https://your-url', api_key: 'key', api_secret: 'secret') -info = egressClient.start_room_composite_egress( +# starting a room composite to S3 +info = api.egress.start_room_composite_egress( 'room-name', LiveKit::Proto::EncodedFileOutput.new( file_type: LiveKit::Proto::EncodedFileType::MP4, @@ -112,7 +200,7 @@ puts info # starting a track composite to RTMP urls = Google::Protobuf::RepeatedField.new(:string, ['rtmp://url1', 'rtmps://url2']) -info = egressClient.start_track_composite_egress( +info = api.egress.start_track_composite_egress( 'room-name', LiveKit::Proto::StreamOutput.new( protocol: LiveKit::Proto::StreamProtocol::RTMP, @@ -126,10 +214,12 @@ puts info ### Environment Variables -You may store credentials in environment variables. If api-key or api-secret is not passed in when creating a `RoomServiceClient` or `AccessToken`, the values in the following env vars will be used: +You may store credentials in environment variables. When the corresponding argument is not passed to `LiveKitAPI` (or `AccessToken`), these are used: +- `LIVEKIT_URL` - `LIVEKIT_API_KEY` - `LIVEKIT_API_SECRET` +- `LIVEKIT_TOKEN` ## License