### Install LiveKitEx Dependency
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Adds the LiveKitEx Elixir SDK to your project's dependencies in the `mix.exs` file.
```elixir
def deps do
[
{:livekitex, "~> 0.1.0"}
]
end
```
--------------------------------
### Generate Basic User Access Token - Livekitex Elixir
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Provides an example of generating a basic access token for a user to join a room. It includes setting user identity, name, metadata, and granting video room access with publishing and subscribing capabilities. The token is then converted to JWT format.
```elixir
# Simple user token with room access
token = Livekitex.AccessToken.create(
"api_key",
"api_secret",
identity: "user123",
name: "John Doe",
metadata: %{role: "presenter", department: "engineering"},
ttl: 3600 # Token valid for 1 hour
)
video_grant = %Livekitex.Grants.VideoGrant{
room_join: true,
room: "my-room",
can_publish: true,
can_subscribe: true,
can_publish_data: true
}
token = Livekitex.AccessToken.set_video_grant(token, video_grant)
{:ok, jwt, claims} = Livekitex.AccessToken.to_jwt(token)
```
--------------------------------
### Elixir Livekitex Error Handling for Room Creation
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
This example illustrates how to handle different error tuples returned by the `Livekitex.RoomService.create_room` function, including `already_exists`, `unauthenticated`, `not_found`, and general `twirp_error` or other reasons. It provides a robust way to manage API call failures.
```elixir
case Livekitex.RoomService.create_room(room_service, "test-room") do
{:ok, room} ->
# Success
IO.puts("Room created: #{room.name}")
{:error, {:already_exists, message}} ->
# Room already exists
IO.puts("Room already exists: #{message}")
{:error, {:unauthenticated, message}} ->
# Invalid API credentials
IO.puts("Authentication failed: #{message}")
{:error, {:not_found, message}} ->
# Resource not found
IO.puts("Not found: #{message}")
{:error, {:twirp_error, reason}} ->
# Connection or communication error
IO.puts("Connection error: #{inspect(reason)}")
{:error, reason} ->
# Other errors
IO.puts("Error: #{inspect(reason)}")
end
```
--------------------------------
### Bash Commands for Running Elixir Project Tests
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Provides common `mix test` commands for running the project's test suite, including options for coverage and targeting specific files. It also outlines how to run integration tests against a live LiveKit server.
```bash
# Run all tests
mix test
# Run tests with coverage
mix test --cover
# Run specific test file
mix test test/livekitex/room_service_test.exs
```
```bash
# Start a LiveKit server in development mode:
# livekit-server --dev
# Run the tests:
mix test
```
--------------------------------
### Elixir Livekitex RoomService Creation with Custom Host/Port
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Demonstrates how to create a `Livekitex.RoomService` client by providing API key, secret, and custom host/port configurations. This is essential for connecting to a specific LiveKit instance.
```elixir
# Create room service with custom options
room_service = Livekitex.RoomService.create(
"api_key",
"api_secret",
host: "livekit.example.com",
port: 443 # Use 443 for HTTPS
)
```
--------------------------------
### Create Room Service Client
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Initializes a client for interacting with the LiveKit Room Service API, requiring API key and secret for authentication.
```elixir
# Create a room service client
room_service = Livekitex.RoomService.create("your_api_key", "your_api_secret")
```
--------------------------------
### Configure LiveKitEx
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Configures the LiveKitEx SDK with LiveKit server credentials and host/port details in `config/config.exs`. It also shows how to configure the underlying Tesla HTTP client.
```elixir
import Config
config :livekitex,
api_key: "your_api_key",
api_secret: "your_api_secret",
host: "localhost", # Your LiveKit server host
port: 7880 # LiveKit HTTP API port (default: 7880)
# Tesla HTTP client configuration
config :tesla, Tesla.Adapter.Finch, name: Livekitex.Finch
```
--------------------------------
### Create Room with Custom Options
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Creates a LiveKit room with advanced configuration options like maximum participants, empty room timeouts, and custom metadata.
```elixir
room_service = Livekitex.RoomService.create("api_key", "api_secret")
# Create a room with custom settings
options = [
max_participants: 50,
empty_timeout: 600, # Auto-delete after 10 minutes of being empty
departure_timeout: 30, # Wait 30 seconds after last participant leaves
metadata: "Conference Room A"
]
{:ok, room} = Livekitex.RoomService.create_room(room_service, "conference-room", options)
# Room details
IO.puts("Room created: #{room.name}")
IO.puts("Room SID: #{room.sid}")
IO.puts("Max participants: #{room.max_participants}")
IO.puts("Creation time: #{room.creation_time}")
```
--------------------------------
### Elixir LiveKit Connection Pool and Client Management
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Manages persistent LiveKit room service clients using GenServer. It demonstrates creating a client with API credentials and host details from application configuration, and provides functions to create, list, and delete rooms via GenServer calls.
```elixir
defmodule MyApp.LiveKitManager do
use GenServer
alias Livekitex.RoomService
def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
def init(_opts) do
# Create a persistent room service client
room_service = RoomService.create(
Application.get_env(:livekitex, :api_key),
Application.get_env(:livekitex, :api_secret),
host: Application.get_env(:livekitex, :host),
port: Application.get_env(:livekitex, :port)
)
{:ok, %{room_service: room_service}}
end
def create_room(name, opts \ []) do
GenServer.call(__MODULE__, {:create_room, name, opts})
end
def list_rooms do
GenServer.call(__MODULE__, :list_rooms)
end
def delete_room(name) do
GenServer.call(__MODULE__, {:delete_room, name})
end
def handle_call({:create_room, name, opts}, _from, state) do
result = RoomService.create_room(state.room_service, name, opts)
{:reply, result, state}
end
def handle_call(:list_rooms, _from, state) do
result = RoomService.list_rooms(state.room_service)
{:reply, result, state}
end
def handle_call({:delete_room, name}, _from, state) do
result = RoomService.delete_room(state.room_service, name)
{:reply, result, state}
end
end
# Add to your application supervision tree
children = [
MyApp.LiveKitManager
]
```
--------------------------------
### Create a New Room
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Creates a new LiveKit room with a specified name. Returns the room details upon successful creation.
```elixir
# Create a new room
{:ok, room} = Livekitex.RoomService.create_room(room_service, "my-room")
IO.inspect(room)
```
--------------------------------
### Configure LiveKitEx with Environment Variables
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Configures the LiveKitEx SDK using environment variables for API key, secret, host, and port, providing default values for host and port.
```elixir
config :livekitex,
api_key: System.get_env("LIVEKIT_API_KEY"),
api_secret: System.get_env("LIVEKIT_API_SECRET"),
host: System.get_env("LIVEKIT_HOST", "localhost"),
port: String.to_integer(System.get_env("LIVEKIT_PORT", "7880"))
```
--------------------------------
### Elixir LiveKit Room Creation with Retry Logic
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Implements robust room creation by handling specific errors like connection refused and server unavailability. It uses exponential backoff for retries, logging warnings for each attempt and errors if creation fails after multiple retries.
```elixir
defmodule MyApp.RoomManager do
alias Livekitex.RoomService
require Logger
def create_room_with_retry(room_service, name, opts \ [], max_retries \ 3) do
do_create_room_with_retry(room_service, name, opts, max_retries, 0)
end
defp do_create_room_with_retry(room_service, name, opts, max_retries, attempt) do
case RoomService.create_room(room_service, name, opts) do
{:ok, room} ->
{:ok, room}
{:error, {:twirp_error, :econnrefused}} when attempt < max_retries ->
Logger.warn("Connection refused, retrying in #{backoff_delay(attempt)}ms")
Process.sleep(backoff_delay(attempt))
do_create_room_with_retry(room_service, name, opts, max_retries, attempt + 1)
{:error, {:unavailable, _}} when attempt < max_retries ->
Logger.warn("Server unavailable, retrying in #{backoff_delay(attempt)}ms")
Process.sleep(backoff_delay(attempt))
do_create_room_with_retry(room_service, name, opts, max_retries, attempt + 1)
{:error, reason} ->
Logger.error("Failed to create room after #{attempt + 1} attempts: #{inspect(reason)}")
{:error, reason}
end
end
defp backoff_delay(attempt) do
# Exponential backoff: 1s, 2s, 4s
:math.pow(2, attempt) * 1000 |> round()
end
end
```
--------------------------------
### Elixir Phoenix LiveView LiveKit Room Integration
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Integrates LiveKit room management into a Phoenix LiveView. The `mount` function ensures a room exists and generates an access token for a given user, assigning room details and the token to the socket assigns. The `render` function displays room information and prepares a container for LiveKit video elements using a `phx-hook`.
```elixir
defmodule MyAppWeb.RoomLive do
use MyAppWeb, :live_view
alias MyApp.{TokenGenerator, LiveKitManager}
@impl true
def mount(%{"room_id" => room_id}, %{"user_id" => user_id}, socket) do
# Ensure room exists
case LiveKitManager.create_room(room_id) do
{:ok, _room} ->
# Generate access token for the user
{:ok, token, _} = TokenGenerator.generate_token(user_id, :presenter, room_id)
socket =
socket
|> assign(:room_id, room_id)
|> assign(:user_id, user_id)
|> assign(:access_token, token)
|> assign(:connected, false)
{:ok, socket}
{:error, reason} ->
{:error, "Failed to create room: #{inspect(reason)}"}
end
end
@impl true
def render(assigns) do
~H"""
Room: <%= @room_id %>
User: <%= @user_id %>
"""
end
end
```
--------------------------------
### Generate Admin Access Token - Livekitex Elixir
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Illustrates the creation of an administrative access token, granting broad permissions for room management tasks such as listing, creating, and recording rooms. This token is essential for backend operations requiring elevated privileges.
```elixir
# Create admin token for room management operations
admin_token = Livekitex.AccessToken.create(
"api_key",
"api_secret",
identity: "admin"
)
admin_grant = %Livekitex.Grants.VideoGrant{
room_admin: true,
room_list: true,
room_create: true,
room_record: true
}
admin_token = Livekitex.AccessToken.set_video_grant(admin_token, admin_grant)
{:ok, admin_jwt, _} = Livekitex.AccessToken.to_jwt(admin_token)
```
--------------------------------
### List All Rooms
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Retrieves a list of all active rooms managed by the LiveKit server. Returns a list of room details.
```elixir
# List all rooms
{:ok, rooms} = Livekitex.RoomService.list_rooms(room_service)
IO.inspect(rooms)
```
--------------------------------
### Generate Role-Based Access Tokens - Livekitex Elixir
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
A comprehensive module for generating access tokens tailored to different user roles (host, presenter, viewer, recorder). Each role is assigned specific permissions for joining rooms, publishing, subscribing, and managing data, ensuring granular control over participant capabilities.
```elixir
defmodule MyApp.TokenGenerator do
alias Livekitex.{AccessToken, Grants}
def generate_token(user_id, role, room_name) do
token = AccessToken.create(
Application.get_env(:livekitex, :api_key),
Application.get_env(:livekitex, :api_secret),
identity: user_id,
name: get_user_name(user_id),
ttl: 7200 # 2 hours
)
video_grant = case role do
:host ->
%Grants.VideoGrant{
room_join: true,
room: room_name,
can_publish: true,
can_subscribe: true,
can_publish_data: true,
can_update_metadata: true
}
:presenter ->
%Grants.VideoGrant{
room_join: true,
room: room_name,
can_publish: true,
can_subscribe: true,
can_publish_data: false
}
:viewer ->
%Grants.VideoGrant{
room_join: true,
room: room_name,
can_publish: false,
can_subscribe: true,
can_publish_data: false
}
:recorder ->
%Grants.VideoGrant{
room_join: true,
room: room_name,
can_publish: true,
can_subscribe: true,
hidden: true,
recorder: true
}
end
token
|> AccessToken.set_video_grant(video_grant)
|> AccessToken.to_jwt()
end
defp get_user_name(user_id) do
# Fetch user name from your database
"User #{user_id}"
end
end
# Usage
{:ok, host_token, _} = MyApp.TokenGenerator.generate_token("host123", :host, "meeting-room")
{:ok, viewer_token, _} = MyApp.TokenGenerator.generate_token("viewer456", :viewer, "meeting-room")
```
--------------------------------
### Set Video Grant for Access Token
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Applies specific video-related permissions (grants) to an access token, such as joining a room, publishing, or subscribing.
```elixir
# Set video permissions
video_grant = %Livekitex.Grants.VideoGrant{
room_join: true,
room: "my-room",
can_publish: true,
can_subscribe: true
}
token = Livekitex.AccessToken.set_video_grant(token, video_grant)
```
--------------------------------
### List and Filter Rooms
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Retrieves rooms from the LiveKit server, with options to filter the results by a list of room names.
```elixir
# List all rooms
{:ok, all_rooms} = Livekitex.RoomService.list_rooms(room_service)
# Filter rooms by name
{:ok, filtered_rooms} = Livekitex.RoomService.list_rooms(
room_service,
names: ["room1", "room2", "room3"]
)
Enum.each(filtered_rooms, fn room ->
IO.puts("Room: #{room.name} (#{room.num_participants} participants)")
end)
```
--------------------------------
### Elixir Tesla HTTP Client Configuration (Finch Adapter, Timeout)
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Shows how to configure the Tesla HTTP client in `config/config.exs` to use the Finch adapter and set a custom request timeout. This affects how the library makes HTTP requests.
```elixir
# In config/config.exs
config :tesla,
adapter: {Tesla.Adapter.Finch, name: Livekitex.Finch},
# Optional: Configure request timeout
timeout: 30_000 # 30 seconds
```
--------------------------------
### Process Webhooks - Livekitex Elixir
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Details how to set up a controller to receive and validate incoming webhooks from LiveKit. It includes reading the request body, extracting the authorization header, validating the signature using the API secret, and processing different event types like room status changes and participant events.
```elixir
defmodule MyApp.WebhookController do
use MyAppWeb, :controller
alias Livekitex.Webhook
def receive_webhook(conn, _params) do
# Get the raw body and authorization header
{:ok, raw_body, _conn} = Plug.Conn.read_body(conn)
auth_header = get_req_header(conn, "authorization") |> List.first()
case Webhook.validate_webhook(raw_body, auth_header, get_api_secret()) do
{:ok, event} ->
process_webhook_event(event)
json(conn, %{status: "ok"})
{:error, reason} ->
Logger.error("Webhook validation failed: #{inspect(reason)}")
conn
|> put_status(400)
|> json(%{error: "Invalid webhook"})
end
end
defp process_webhook_event(%{event: event_type} = event) do
case event_type do
"room_started" ->
Logger.info("Room started: #{event.room.name}")
# Handle room started event
"room_finished" ->
Logger.info("Room finished: #{event.room.name}")
# Handle room finished event
"participant_joined" ->
Logger.info("Participant joined: #{event.participant.identity}")
# Handle participant joined event
"participant_left" ->
Logger.info("Participant left: #{event.participant.identity}")
# Handle participant left event
"track_published" ->
Logger.info("Track published: #{event.track.sid}")
# Handle track published event
"track_unpublished" ->
Logger.info("Track unpublished: #{event.track.sid}")
# Handle track unpublished event
_ ->
Logger.info("Unhandled webhook event: #{event_type}")
end
end
defp get_api_secret do
Application.get_env(:livekitex, :api_secret)
end
end
```
--------------------------------
### Generate Access Token
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Generates a base access token for a user with specified identity and name. This token is then used to set grants.
```elixir
# Create an access token for a user
token = Livekitex.AccessToken.create(
"your_api_key",
"your_api_secret",
identity: "user123",
name: "John Doe"
)
```
--------------------------------
### List Participants in a Room
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Retrieves a list of all participants currently connected to a specific LiveKit room, including their identity, state, and tracks.
```elixir
# List all participants in a room
{:ok, participants} = Livekitex.RoomService.list_participants(room_service, "my-room")
Enum.each(participants, fn participant ->
IO.puts("Participant: #{participant.identity} (#{participant.name})")
IO.puts(" State: #{participant.state}")
IO.puts(" Joined at: #{participant.joined_at}")
IO.puts(" Is publisher: #{participant.is_publisher}")
IO.puts(" Tracks: #{length(participant.tracks)}")
end)
```
--------------------------------
### Elixir Oban Worker for LiveKit Room Cleanup
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
This snippet defines an Oban worker to periodically clean up empty rooms in LiveKit. It lists rooms, filters for empty ones, and deletes them using `LiveKitManager`. It requires `Oban` and `MyApp.LiveKitManager` for its operations.
```elixir
defmodule MyApp.Workers.RoomCleanup do
use Oban.Worker, queue: :default, max_attempts: 3
alias MyApp.LiveKitManager
require Logger
@impl Oban.Worker
def perform(%Oban.Job{args: %{"action" => "cleanup_empty_rooms"}}) do
case LiveKitManager.list_rooms() do
{:ok, rooms} ->
empty_rooms = Enum.filter(rooms, fn room -> room.num_participants == 0 end)
Enum.each(empty_rooms, fn room ->
case LiveKitManager.delete_room(room.name) do
:ok ->
Logger.info("Cleaned up empty room: #{room.name}")
{:error, reason} ->
Logger.error("Failed to cleanup room #{room.name}: #{inspect(reason)}")
end
end)
{:ok, "Cleaned up #{length(empty_rooms)} empty rooms"}
{:error, reason} ->
Logger.error("Failed to list rooms for cleanup: #{inspect(reason)}")
{:error, reason}
end
end
# Schedule cleanup job every hour
def schedule_cleanup do
%{action: "cleanup_empty_rooms"}
|> __MODULE__.new(schedule_in: 3600)
|> Oban.insert()
end
end
```
--------------------------------
### Generate JWT Access Token
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Converts the prepared access token object into a JSON Web Token (JWT) string, which can be used by clients to connect to LiveKit.
```elixir
# Generate JWT
{:ok, jwt, _claims} = Livekitex.AccessToken.to_jwt(token)
IO.puts("Access token: #{jwt}")
```
--------------------------------
### Mute Published Audio Track
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Mutes or unmutes a specific audio track published by a participant in a room. Requires room name, participant identity, and track SID.
```elixir
# Mute a participant's audio track
{:ok, track} = Livekitex.RoomService.mute_published_track(
room_service,
"my-room",
"user123",
"track_sid_audio",
true # muted = true
)
```
--------------------------------
### Unmute Participant Video Track - Livekitex Elixir
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Demonstrates how to unmute a specific participant's video track within a room. This operation requires the room service, room name, participant's identity, and the track's SID. It returns the updated track information.
```elixir
# Unmute a participant's video track
{:ok, track} = Livekitex.RoomService.mute_published_track(
room_service,
"my-room",
"user123",
"track_sid_video",
false # muted = false
)
IO.puts("Track #{track.sid} mute status: #{track.muted}")
```
--------------------------------
### Delete a Room
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Deletes a LiveKit room by its name. This operation is idempotent and returns `:ok` on success.
```elixir
# Delete a room
:ok = Livekitex.RoomService.delete_room(room_service, "my-room")
```
--------------------------------
### Remove Participant from Room
Source: https://github.com/rocket4ce/livekitex/blob/main/README.md
Removes a specific participant from a LiveKit room by their identity. This action disconnects the participant.
```elixir
# Remove a participant from a room
:ok = Livekitex.RoomService.remove_participant(room_service, "my-room", "user123")
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.