### 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.