├── .ruby-version ├── .tool-versions ├── .rspec ├── CHANGELOG.md ├── .github ├── banner_dark.png ├── banner_light.png └── workflows │ └── test.yml ├── .gitmodules ├── lib ├── livekit │ ├── version.rb │ ├── proto │ │ ├── livekit_agent_twirp.rb │ │ ├── livekit_models_twirp.rb │ │ ├── livekit_metrics_twirp.rb │ │ ├── livekit_webhook_twirp.rb │ │ ├── livekit_agent_dispatch_twirp.rb │ │ ├── livekit_ingress_twirp.rb │ │ ├── livekit_webhook_pb.rb │ │ ├── livekit_egress_twirp.rb │ │ ├── livekit_room_twirp.rb │ │ ├── livekit_sip_twirp.rb │ │ ├── livekit_agent_dispatch_pb.rb │ │ ├── livekit_metrics_pb.rb │ │ ├── livekit_agent_pb.rb │ │ ├── livekit_ingress_pb.rb │ │ ├── livekit_room_pb.rb │ │ ├── livekit_egress_pb.rb │ │ ├── livekit_sip_pb.rb │ │ └── livekit_models_pb.rb │ ├── token_verifier.rb │ ├── auth_mixin.rb │ ├── utils.rb │ ├── access_token.rb │ ├── agent_dispatch_service_client.rb │ ├── ingress_service_client.rb │ ├── grants.rb │ ├── room_service_client.rb │ ├── sip_service_client.rb │ └── egress_service_client.rb └── livekit.rb ├── bin ├── console ├── bootstrap.sh ├── pry ├── yri ├── rake ├── yard ├── ldiff ├── yardoc ├── coderay ├── rspec ├── rubocop ├── htmldiff ├── ruby-parse ├── ruby-rewrite └── bundle ├── spec ├── livekit │ ├── core_spec.rb │ ├── token_verifier_spec.rb │ ├── access_token_spec.rb │ └── grants_spec.rb └── spec_helper.rb ├── .gitignore ├── Gemfile ├── .editorconfig ├── .rubocop.yml ├── NOTICE ├── .rubocop_todo.yml ├── Rakefile ├── livekit_server_sdk.gemspec ├── Gemfile.lock ├── CODE_OF_CONDUCT.md ├── README.md └── LICENSE /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.1.2 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | ruby 2.6.8 2 | protoc 3.18.0 3 | golang 1.15.15 4 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [Unreleased] 2 | 3 | ## [0.1.0] - 2021-07-25 4 | 5 | - Initial release 6 | -------------------------------------------------------------------------------- /.github/banner_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/livekit/server-sdk-ruby/HEAD/.github/banner_dark.png -------------------------------------------------------------------------------- /.github/banner_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/livekit/server-sdk-ruby/HEAD/.github/banner_light.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "protocol"] 2 | path = protocol 3 | url = https://github.com/livekit/protocol 4 | -------------------------------------------------------------------------------- /lib/livekit/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module LiveKit 4 | VERSION = "0.8.3" 5 | end 6 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'bundler/setup' 5 | require 'livekit' 6 | 7 | require 'pry' 8 | Pry.start 9 | -------------------------------------------------------------------------------- /bin/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Ensure protoc and Go are installed" 4 | 5 | go install github.com/arthurnn/twirp-ruby/protoc-gen-twirp_ruby@latest 6 | -------------------------------------------------------------------------------- /spec/livekit/core_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe LiveKit do 4 | it 'has a version number' do 5 | expect(LiveKit::VERSION).not_to be nil 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_agent_twirp.rb: -------------------------------------------------------------------------------- 1 | # Code generated by protoc-gen-twirp_ruby 1.14.1, DO NOT EDIT. 2 | require 'twirp' 3 | require_relative 'livekit_agent_pb.rb' 4 | 5 | module LiveKit 6 | module Proto 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_models_twirp.rb: -------------------------------------------------------------------------------- 1 | # Code generated by protoc-gen-twirp_ruby 1.14.1, DO NOT EDIT. 2 | require 'twirp' 3 | require_relative 'livekit_models_pb.rb' 4 | 5 | module LiveKit 6 | module Proto 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_metrics_twirp.rb: -------------------------------------------------------------------------------- 1 | # Code generated by protoc-gen-twirp_ruby 1.14.1, DO NOT EDIT. 2 | require 'twirp' 3 | require_relative 'livekit_metrics_pb.rb' 4 | 5 | module LiveKit 6 | module Proto 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_webhook_twirp.rb: -------------------------------------------------------------------------------- 1 | # Code generated by protoc-gen-twirp_ruby 1.14.1, DO NOT EDIT. 2 | require 'twirp' 3 | require_relative 'livekit_webhook_pb.rb' 4 | 5 | module LiveKit 6 | module Proto 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /.bundle/ 3 | /.yardoc 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | /vendor/bundle 11 | 12 | #dev 13 | test/ 14 | livekit-server-sdk-*.gem 15 | 16 | # rspec failure tracking 17 | .rspec_status 18 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | gemspec 6 | 7 | gem 'rake' 8 | 9 | group :test do 10 | gem 'rspec' 11 | end 12 | 13 | group :development do 14 | gem 'pry' 15 | gem 'pry-doc' 16 | gem 'yard' 17 | end 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | require: 4 | - rubocop-rake 5 | - rubocop-rspec 6 | 7 | AllCops: 8 | Exclude: 9 | - 'bin/**/*' 10 | - 'lib/livekit/proto/**/*' 11 | - 'vendor/**/*' 12 | NewCops: enable 13 | TargetRubyVersion: 2.6 14 | 15 | Layout/LineLength: 16 | Max: 100 17 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../lib/livekit' 4 | 5 | RSpec.configure do |config| 6 | # Enable flags like --only-failures and --next-failure 7 | config.example_status_persistence_file_path = '.rspec_status' 8 | 9 | # Disable RSpec exposing methods globally on `Module` and `main` 10 | config.disable_monkey_patching! 11 | 12 | config.expect_with :rspec do |c| 13 | c.syntax = :expect 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/livekit.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "livekit/access_token" 4 | require "livekit/utils" 5 | require "livekit/grants" 6 | require "livekit/token_verifier" 7 | require "livekit/version" 8 | 9 | # required since generated protobufs does use `require` instead of `require_relative` 10 | $LOAD_PATH.unshift(File.expand_path("livekit/proto", __dir__)) 11 | require "livekit/room_service_client" 12 | require "livekit/egress_service_client" 13 | require "livekit/ingress_service_client" 14 | require "livekit/sip_service_client" 15 | require "livekit/agent_dispatch_service_client" 16 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2021 LiveKit, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /lib/livekit/token_verifier.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "jwt" 4 | 5 | module LiveKit 6 | class TokenVerifier 7 | def initialize(api_key: nil, api_secret: nil) 8 | @api_key = api_key 9 | @api_secret = api_secret 10 | end 11 | 12 | def verify(token) 13 | decoded_token = JWT.decode(token, @api_secret, true, algorithm: AccessToken::SIGNING_ALGORITHM) 14 | decoded = decoded_token.first 15 | if decoded["iss"] != @api_key 16 | raise "Invalid issuer" 17 | end 18 | ClaimGrant.from_hash(decoded) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/livekit/auth_mixin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module LiveKit 4 | # Create authenticated headers when keys are provided 5 | module AuthMixin 6 | def auth_header( 7 | video_grant: nil, 8 | sip_grant: nil 9 | ) 10 | headers = {} 11 | t = ::LiveKit::AccessToken.new(api_key: @api_key, api_secret: @api_secret) 12 | if video_grant != nil 13 | t.video_grant = video_grant 14 | end 15 | if sip_grant != nil 16 | t.sip_grant = sip_grant 17 | end 18 | headers["Authorization"] = "Bearer #{t.to_jwt}" 19 | headers["User-Agent"] = "LiveKit Ruby SDK" 20 | headers 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/livekit/utils.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module LiveKit 4 | module Utils 5 | # Utility function to convert WebSocket URLs to HTTP URLs 6 | def to_http_url(url) 7 | if url.start_with?("ws") 8 | # Replace 'ws' prefix with 'http' 9 | url.sub(/^ws/, "http") 10 | else 11 | url 12 | end 13 | end 14 | module_function :to_http_url 15 | 16 | module StringifyKeysRefinement 17 | refine Hash do 18 | def stringify_keys 19 | transform_keys(&:to_s).transform_values do |value| 20 | value.is_a?(Hash) ? value.stringify_keys : value 21 | end 22 | end 23 | end 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2021-08-08 21:38:20 UTC using RuboCop version 1.18.4. 4 | # The point is for the user to remove these configuration records 5 | # one by one as the offenses are removed from the code base. 6 | # Note that changes in the inspected code, or installation of new 7 | # versions of RuboCop, may require this file to be generated again. 8 | 9 | # Offense count: 1 10 | # Cop supports --auto-correct. 11 | RSpec/ExpectActual: 12 | Exclude: 13 | - 'spec/routing/**/*' 14 | - 'spec/livekit/ruby_spec.rb' 15 | 16 | # Offense count: 1 17 | # Configuration parameters: AllowedConstants. 18 | Style/Documentation: 19 | Exclude: 20 | - 'spec/**/*' 21 | - 'test/**/*' 22 | - 'lib/livekit/proto.rb' 23 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_agent_dispatch_twirp.rb: -------------------------------------------------------------------------------- 1 | # Code generated by protoc-gen-twirp_ruby 1.14.1, DO NOT EDIT. 2 | require 'twirp' 3 | require_relative 'livekit_agent_dispatch_pb.rb' 4 | 5 | module LiveKit 6 | module Proto 7 | class AgentDispatchServiceService < ::Twirp::Service 8 | package 'livekit' 9 | service 'AgentDispatchService' 10 | rpc :CreateDispatch, CreateAgentDispatchRequest, AgentDispatch, :ruby_method => :create_dispatch 11 | rpc :DeleteDispatch, DeleteAgentDispatchRequest, AgentDispatch, :ruby_method => :delete_dispatch 12 | rpc :ListDispatch, ListAgentDispatchRequest, ListAgentDispatchResponse, :ruby_method => :list_dispatch 13 | end 14 | 15 | class AgentDispatchServiceClient < ::Twirp::Client 16 | client_for AgentDispatchServiceService 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_ingress_twirp.rb: -------------------------------------------------------------------------------- 1 | # Code generated by protoc-gen-twirp_ruby 1.14.1, DO NOT EDIT. 2 | require 'twirp' 3 | require_relative 'livekit_ingress_pb.rb' 4 | 5 | module LiveKit 6 | module Proto 7 | class IngressService < ::Twirp::Service 8 | package 'livekit' 9 | service 'Ingress' 10 | rpc :CreateIngress, CreateIngressRequest, IngressInfo, :ruby_method => :create_ingress 11 | rpc :UpdateIngress, UpdateIngressRequest, IngressInfo, :ruby_method => :update_ingress 12 | rpc :ListIngress, ListIngressRequest, ListIngressResponse, :ruby_method => :list_ingress 13 | rpc :DeleteIngress, DeleteIngressRequest, IngressInfo, :ruby_method => :delete_ingress 14 | end 15 | 16 | class IngressClient < ::Twirp::Client 17 | client_for IngressService 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | name: Test 3 | jobs: 4 | test: 5 | name: Test on ruby ${{ matrix.ruby_version }} with options - ${{ toJson(matrix.options) }} 6 | runs-on: ${{ matrix.os }} 7 | strategy: 8 | matrix: 9 | include: 10 | - { os: ubuntu-latest, ruby_version: "3.0" } 11 | - { os: ubuntu-latest, ruby_version: "3.3" } 12 | - { os: ubuntu-latest, ruby_version: "jruby-9.4" } 13 | steps: 14 | - name: Setup Ruby, JRuby and TruffleRuby 15 | uses: ruby/setup-ruby@v1.190.0 16 | with: 17 | bundler: 1 18 | ruby-version: ${{ matrix.ruby_version }} 19 | - name: Checkout code 20 | uses: actions/checkout@v2 21 | - name: Run tests 22 | run: | 23 | gem install bundler:2.3.7 24 | bundle install --jobs 4 --retry 3 25 | bundle exec rspec 26 | -------------------------------------------------------------------------------- /bin/pry: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'pry' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("pry", "pry") 30 | -------------------------------------------------------------------------------- /bin/yri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("yard", "yri") 30 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rake' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rake", "rake") 30 | -------------------------------------------------------------------------------- /bin/yard: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yard' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("yard", "yard") 30 | -------------------------------------------------------------------------------- /bin/ldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("diff-lcs", "ldiff") 30 | -------------------------------------------------------------------------------- /bin/yardoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yardoc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("yard", "yardoc") 30 | -------------------------------------------------------------------------------- /bin/coderay: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'coderay' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("coderay", "coderay") 30 | -------------------------------------------------------------------------------- /bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rspec' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rspec-core", "rspec") 30 | -------------------------------------------------------------------------------- /bin/rubocop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rubocop' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rubocop", "rubocop") 30 | -------------------------------------------------------------------------------- /bin/htmldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'htmldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("diff-lcs", "htmldiff") 30 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task default: %i[spec] 7 | 8 | desc "Generate protobuf stubs" 9 | task :proto do 10 | system("protoc", 11 | "--proto_path=protocol/protobufs", 12 | "--ruby_out=lib/livekit/proto", 13 | "--twirp_ruby_out=lib/livekit/proto", 14 | "-Iprotocol", 15 | "./protocol/protobufs/livekit_agent.proto", 16 | "./protocol/protobufs/livekit_agent_dispatch.proto", 17 | "./protocol/protobufs/livekit_egress.proto", 18 | "./protocol/protobufs/livekit_ingress.proto", 19 | "./protocol/protobufs/livekit_sip.proto", 20 | "./protocol/protobufs/livekit_metrics.proto", 21 | "./protocol/protobufs/livekit_models.proto", 22 | "./protocol/protobufs/livekit_room.proto", 23 | "./protocol/protobufs/livekit_webhook.proto") 24 | end 25 | -------------------------------------------------------------------------------- /bin/ruby-parse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-parse' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("parser", "ruby-parse") 30 | -------------------------------------------------------------------------------- /bin/ruby-rewrite: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-rewrite' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("parser", "ruby-rewrite") 30 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_webhook_pb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: livekit_webhook.proto 4 | 5 | require 'google/protobuf' 6 | 7 | require 'livekit_models_pb' 8 | require 'livekit_egress_pb' 9 | require 'livekit_ingress_pb' 10 | 11 | 12 | descriptor_data = "\n\x15livekit_webhook.proto\x12\x07livekit\x1a\x14livekit_models.proto\x1a\x14livekit_egress.proto\x1a\x15livekit_ingress.proto\"\x9b\x02\n\x0cWebhookEvent\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x1b\n\x04room\x18\x02 \x01(\x0b\x32\r.livekit.Room\x12-\n\x0bparticipant\x18\x03 \x01(\x0b\x32\x18.livekit.ParticipantInfo\x12(\n\x0b\x65gress_info\x18\t \x01(\x0b\x32\x13.livekit.EgressInfo\x12*\n\x0cingress_info\x18\n \x01(\x0b\x32\x14.livekit.IngressInfo\x12!\n\x05track\x18\x08 \x01(\x0b\x32\x12.livekit.TrackInfo\x12\n\n\x02id\x18\x06 \x01(\t\x12\x12\n\ncreated_at\x18\x07 \x01(\x03\x12\x17\n\x0bnum_dropped\x18\x0b \x01(\x05\x42\x02\x18\x01\x42\x46Z#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" 13 | 14 | pool = Google::Protobuf::DescriptorPool.generated_pool 15 | pool.add_serialized_file(descriptor_data) 16 | 17 | module LiveKit 18 | module Proto 19 | WebhookEvent = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.WebhookEvent").msgclass 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_egress_twirp.rb: -------------------------------------------------------------------------------- 1 | # Code generated by protoc-gen-twirp_ruby 1.14.1, DO NOT EDIT. 2 | require 'twirp' 3 | require_relative 'livekit_egress_pb.rb' 4 | 5 | module LiveKit 6 | module Proto 7 | class EgressService < ::Twirp::Service 8 | package 'livekit' 9 | service 'Egress' 10 | rpc :StartRoomCompositeEgress, RoomCompositeEgressRequest, EgressInfo, :ruby_method => :start_room_composite_egress 11 | rpc :StartWebEgress, WebEgressRequest, EgressInfo, :ruby_method => :start_web_egress 12 | rpc :StartParticipantEgress, ParticipantEgressRequest, EgressInfo, :ruby_method => :start_participant_egress 13 | rpc :StartTrackCompositeEgress, TrackCompositeEgressRequest, EgressInfo, :ruby_method => :start_track_composite_egress 14 | rpc :StartTrackEgress, TrackEgressRequest, EgressInfo, :ruby_method => :start_track_egress 15 | rpc :UpdateLayout, UpdateLayoutRequest, EgressInfo, :ruby_method => :update_layout 16 | rpc :UpdateStream, UpdateStreamRequest, EgressInfo, :ruby_method => :update_stream 17 | rpc :ListEgress, ListEgressRequest, ListEgressResponse, :ruby_method => :list_egress 18 | rpc :StopEgress, StopEgressRequest, EgressInfo, :ruby_method => :stop_egress 19 | end 20 | 21 | class EgressClient < ::Twirp::Client 22 | client_for EgressService 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /livekit_server_sdk.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "lib/livekit/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "livekit-server-sdk" 7 | spec.version = LiveKit::VERSION 8 | spec.authors = ["Omri Gabay", "David Zhao"] 9 | spec.email = ["omri@omrigabay.me", "dz@livekit.io"] 10 | 11 | spec.summary = "LiveKit Server SDK for Ruby" 12 | spec.homepage = "https://livekit.io" 13 | spec.license = "Apache-2.0" 14 | spec.required_ruby_version = ">= 2.6.0" 15 | 16 | # spec.metadata["homepage_uri"] = spec.homepage 17 | # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." 18 | # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." 19 | 20 | # Specify which files should be added to the gem when it is released. 21 | # The `git ls-files -z` loads the files in the RubyGem that have been added into git. 22 | spec.files = Dir.chdir(File.expand_path(__dir__)) do 23 | `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) } 24 | end 25 | spec.bindir = "exe" 26 | spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } 27 | spec.require_paths = ["lib"] 28 | 29 | spec.add_dependency "google-protobuf", "~> 4.30", ">= 4.30.2" 30 | spec.add_dependency "jwt", ">= 2.2.3", "< 3.0" 31 | spec.add_dependency "twirp", "~> 1.13", ">= 1.13.1" 32 | 33 | # For more information and examples about making a new gem, checkout our 34 | # guide at: https://bundler.io/guides/creating_gem.html 35 | end 36 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | livekit-server-sdk (0.8.3) 5 | google-protobuf (~> 4.30, >= 4.30.2) 6 | jwt (>= 2.2.3, < 3.0) 7 | twirp (~> 1.13, >= 1.13.1) 8 | 9 | GEM 10 | remote: https://rubygems.org/ 11 | specs: 12 | base64 (0.2.0) 13 | bigdecimal (3.1.9) 14 | coderay (1.1.3) 15 | diff-lcs (1.5.0) 16 | faraday (2.13.1) 17 | faraday-net_http (>= 2.0, < 3.5) 18 | json 19 | logger 20 | faraday-net_http (3.4.0) 21 | net-http (>= 0.5.0) 22 | google-protobuf (4.30.2) 23 | bigdecimal 24 | rake (>= 13) 25 | google-protobuf (4.30.2-x86_64-linux) 26 | bigdecimal 27 | rake (>= 13) 28 | json (2.11.3) 29 | jwt (2.8.2) 30 | base64 31 | logger (1.7.0) 32 | method_source (1.0.0) 33 | net-http (0.6.0) 34 | uri 35 | pry (0.14.2) 36 | coderay (~> 1.1) 37 | method_source (~> 1.0) 38 | pry-doc (1.4.0) 39 | pry (~> 0.11) 40 | yard (~> 0.9.11) 41 | rack (3.1.13) 42 | rake (13.2.1) 43 | rspec (3.12.0) 44 | rspec-core (~> 3.12.0) 45 | rspec-expectations (~> 3.12.0) 46 | rspec-mocks (~> 3.12.0) 47 | rspec-core (3.12.1) 48 | rspec-support (~> 3.12.0) 49 | rspec-expectations (3.12.2) 50 | diff-lcs (>= 1.2.0, < 2.0) 51 | rspec-support (~> 3.12.0) 52 | rspec-mocks (3.12.3) 53 | diff-lcs (>= 1.2.0, < 2.0) 54 | rspec-support (~> 3.12.0) 55 | rspec-support (3.12.0) 56 | twirp (1.13.1) 57 | faraday (< 3) 58 | google-protobuf (>= 3.25, < 5.a) 59 | rack (>= 2.2.3) 60 | uri (1.0.3) 61 | webrick (1.7.0) 62 | yard (0.9.28) 63 | webrick (~> 1.7.0) 64 | 65 | PLATFORMS 66 | ruby 67 | x86_64-linux 68 | 69 | DEPENDENCIES 70 | livekit-server-sdk! 71 | pry 72 | pry-doc 73 | rake 74 | rspec 75 | yard 76 | 77 | BUNDLED WITH 78 | 2.3.7 79 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_room_twirp.rb: -------------------------------------------------------------------------------- 1 | # Code generated by protoc-gen-twirp_ruby 1.14.1, DO NOT EDIT. 2 | require 'twirp' 3 | require_relative 'livekit_room_pb.rb' 4 | 5 | module LiveKit 6 | module Proto 7 | class RoomServiceService < ::Twirp::Service 8 | package 'livekit' 9 | service 'RoomService' 10 | rpc :CreateRoom, CreateRoomRequest, Room, :ruby_method => :create_room 11 | rpc :ListRooms, ListRoomsRequest, ListRoomsResponse, :ruby_method => :list_rooms 12 | rpc :DeleteRoom, DeleteRoomRequest, DeleteRoomResponse, :ruby_method => :delete_room 13 | rpc :ListParticipants, ListParticipantsRequest, ListParticipantsResponse, :ruby_method => :list_participants 14 | rpc :GetParticipant, RoomParticipantIdentity, ParticipantInfo, :ruby_method => :get_participant 15 | rpc :RemoveParticipant, RoomParticipantIdentity, RemoveParticipantResponse, :ruby_method => :remove_participant 16 | rpc :MutePublishedTrack, MuteRoomTrackRequest, MuteRoomTrackResponse, :ruby_method => :mute_published_track 17 | rpc :UpdateParticipant, UpdateParticipantRequest, ParticipantInfo, :ruby_method => :update_participant 18 | rpc :UpdateSubscriptions, UpdateSubscriptionsRequest, UpdateSubscriptionsResponse, :ruby_method => :update_subscriptions 19 | rpc :SendData, SendDataRequest, SendDataResponse, :ruby_method => :send_data 20 | rpc :UpdateRoomMetadata, UpdateRoomMetadataRequest, Room, :ruby_method => :update_room_metadata 21 | rpc :ForwardParticipant, ForwardParticipantRequest, ForwardParticipantResponse, :ruby_method => :forward_participant 22 | rpc :MoveParticipant, MoveParticipantRequest, MoveParticipantResponse, :ruby_method => :move_participant 23 | rpc :PerformRpc, PerformRpcRequest, PerformRpcResponse, :ruby_method => :perform_rpc 24 | end 25 | 26 | class RoomServiceClient < ::Twirp::Client 27 | client_for RoomServiceService 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/livekit/token_verifier_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe LiveKit::TokenVerifier do 4 | it "verifies valid tokens" do 5 | token = LiveKit::AccessToken.new(api_key: TEST_KEY, api_secret: TEST_SECRET, 6 | identity: "user") 7 | token.name = "name" 8 | token.video_grant = LiveKit::VideoGrant.new(roomJoin: true, room: "testroom") 9 | token.attributes = { "mykey" => "myvalue" } 10 | jwt = token.to_jwt 11 | v = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET) 12 | grant = v.verify(jwt) 13 | expect(grant.video.roomJoin).to eq(true) 14 | expect(grant.video.room).to eq("testroom") 15 | expect(grant.name).to eq("name") 16 | expect(grant.identity).to eq("user") 17 | expect(grant.attributes["mykey"]).to eq("myvalue") 18 | end 19 | 20 | it "fails on expired tokens" do 21 | token = LiveKit::AccessToken.new(api_key: TEST_KEY, api_secret: TEST_SECRET, 22 | identity: "test_identity", ttl: -10) 23 | token.video_grant = LiveKit::VideoGrant.new(roomJoin: true) 24 | jwt = token.to_jwt 25 | 26 | v = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET) 27 | expect { v.verify(jwt) }.to raise_error(JWT::ExpiredSignature) 28 | end 29 | 30 | it "fails on invalid secret" do 31 | token = LiveKit::AccessToken.new(api_key: TEST_KEY, api_secret: TEST_SECRET, 32 | identity: "test_identity") 33 | token.video_grant = LiveKit::VideoGrant.new(roomJoin: true) 34 | jwt = token.to_jwt 35 | 36 | v = described_class.new(api_key: TEST_KEY, api_secret: "wrong-secret") 37 | expect { v.verify(jwt) }.to raise_error(JWT::VerificationError) 38 | end 39 | 40 | it "fails on invalid api-key" do 41 | token = LiveKit::AccessToken.new(api_key: TEST_KEY, api_secret: TEST_SECRET, 42 | identity: "test_identity") 43 | token.video_grant = LiveKit::VideoGrant.new(roomJoin: true) 44 | jwt = token.to_jwt 45 | 46 | v = described_class.new(api_key: "wrong key", api_secret: TEST_SECRET) 47 | expect { v.verify(jwt) }.to raise_error 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_sip_twirp.rb: -------------------------------------------------------------------------------- 1 | # Code generated by protoc-gen-twirp_ruby 1.14.1, DO NOT EDIT. 2 | require 'twirp' 3 | require_relative 'livekit_sip_pb.rb' 4 | 5 | module LiveKit 6 | module Proto 7 | class SIPService < ::Twirp::Service 8 | package 'livekit' 9 | service 'SIP' 10 | rpc :ListSIPTrunk, ListSIPTrunkRequest, ListSIPTrunkResponse, :ruby_method => :list_s_i_p_trunk 11 | rpc :CreateSIPInboundTrunk, CreateSIPInboundTrunkRequest, SIPInboundTrunkInfo, :ruby_method => :create_s_i_p_inbound_trunk 12 | rpc :CreateSIPOutboundTrunk, CreateSIPOutboundTrunkRequest, SIPOutboundTrunkInfo, :ruby_method => :create_s_i_p_outbound_trunk 13 | rpc :UpdateSIPInboundTrunk, UpdateSIPInboundTrunkRequest, SIPInboundTrunkInfo, :ruby_method => :update_s_i_p_inbound_trunk 14 | rpc :UpdateSIPOutboundTrunk, UpdateSIPOutboundTrunkRequest, SIPOutboundTrunkInfo, :ruby_method => :update_s_i_p_outbound_trunk 15 | rpc :GetSIPInboundTrunk, GetSIPInboundTrunkRequest, GetSIPInboundTrunkResponse, :ruby_method => :get_s_i_p_inbound_trunk 16 | rpc :GetSIPOutboundTrunk, GetSIPOutboundTrunkRequest, GetSIPOutboundTrunkResponse, :ruby_method => :get_s_i_p_outbound_trunk 17 | rpc :ListSIPInboundTrunk, ListSIPInboundTrunkRequest, ListSIPInboundTrunkResponse, :ruby_method => :list_s_i_p_inbound_trunk 18 | rpc :ListSIPOutboundTrunk, ListSIPOutboundTrunkRequest, ListSIPOutboundTrunkResponse, :ruby_method => :list_s_i_p_outbound_trunk 19 | rpc :DeleteSIPTrunk, DeleteSIPTrunkRequest, SIPTrunkInfo, :ruby_method => :delete_s_i_p_trunk 20 | rpc :CreateSIPDispatchRule, CreateSIPDispatchRuleRequest, SIPDispatchRuleInfo, :ruby_method => :create_s_i_p_dispatch_rule 21 | rpc :UpdateSIPDispatchRule, UpdateSIPDispatchRuleRequest, SIPDispatchRuleInfo, :ruby_method => :update_s_i_p_dispatch_rule 22 | rpc :ListSIPDispatchRule, ListSIPDispatchRuleRequest, ListSIPDispatchRuleResponse, :ruby_method => :list_s_i_p_dispatch_rule 23 | rpc :DeleteSIPDispatchRule, DeleteSIPDispatchRuleRequest, SIPDispatchRuleInfo, :ruby_method => :delete_s_i_p_dispatch_rule 24 | rpc :CreateSIPParticipant, CreateSIPParticipantRequest, SIPParticipantInfo, :ruby_method => :create_s_i_p_participant 25 | rpc :TransferSIPParticipant, TransferSIPParticipantRequest, Google::Protobuf::Empty, :ruby_method => :transfer_s_i_p_participant 26 | end 27 | 28 | class SIPClient < ::Twirp::Client 29 | client_for SIPService 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_agent_dispatch_pb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: livekit_agent_dispatch.proto 4 | 5 | require 'google/protobuf' 6 | 7 | require 'livekit_agent_pb' 8 | 9 | 10 | descriptor_data = "\n\x1clivekit_agent_dispatch.proto\x12\x07livekit\x1a\x13livekit_agent.proto\"P\n\x1a\x43reateAgentDispatchRequest\x12\x12\n\nagent_name\x18\x01 \x01(\t\x12\x0c\n\x04room\x18\x02 \x01(\t\x12\x10\n\x08metadata\x18\x03 \x01(\t\"9\n\x11RoomAgentDispatch\x12\x12\n\nagent_name\x18\x01 \x01(\t\x12\x10\n\x08metadata\x18\x02 \x01(\t\"?\n\x1a\x44\x65leteAgentDispatchRequest\x12\x13\n\x0b\x64ispatch_id\x18\x01 \x01(\t\x12\x0c\n\x04room\x18\x02 \x01(\t\"=\n\x18ListAgentDispatchRequest\x12\x13\n\x0b\x64ispatch_id\x18\x01 \x01(\t\x12\x0c\n\x04room\x18\x02 \x01(\t\"M\n\x19ListAgentDispatchResponse\x12\x30\n\x10\x61gent_dispatches\x18\x01 \x03(\x0b\x32\x16.livekit.AgentDispatch\"{\n\rAgentDispatch\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nagent_name\x18\x02 \x01(\t\x12\x0c\n\x04room\x18\x03 \x01(\t\x12\x10\n\x08metadata\x18\x04 \x01(\t\x12*\n\x05state\x18\x05 \x01(\x0b\x32\x1b.livekit.AgentDispatchState\"X\n\x12\x41gentDispatchState\x12\x1a\n\x04jobs\x18\x01 \x03(\x0b\x32\x0c.livekit.Job\x12\x12\n\ncreated_at\x18\x02 \x01(\x03\x12\x12\n\ndeleted_at\x18\x03 \x01(\x03\x32\x8b\x02\n\x14\x41gentDispatchService\x12M\n\x0e\x43reateDispatch\x12#.livekit.CreateAgentDispatchRequest\x1a\x16.livekit.AgentDispatch\x12M\n\x0e\x44\x65leteDispatch\x12#.livekit.DeleteAgentDispatchRequest\x1a\x16.livekit.AgentDispatch\x12U\n\x0cListDispatch\x12!.livekit.ListAgentDispatchRequest\x1a\".livekit.ListAgentDispatchResponseBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" 11 | 12 | pool = Google::Protobuf::DescriptorPool.generated_pool 13 | pool.add_serialized_file(descriptor_data) 14 | 15 | module LiveKit 16 | module Proto 17 | CreateAgentDispatchRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateAgentDispatchRequest").msgclass 18 | RoomAgentDispatch = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RoomAgentDispatch").msgclass 19 | DeleteAgentDispatchRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DeleteAgentDispatchRequest").msgclass 20 | ListAgentDispatchRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListAgentDispatchRequest").msgclass 21 | ListAgentDispatchResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListAgentDispatchResponse").msgclass 22 | AgentDispatch = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AgentDispatch").msgclass 23 | AgentDispatchState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AgentDispatchState").msgclass 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/livekit/access_token.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "jwt" 4 | 5 | module LiveKit 6 | class AccessToken 7 | # 10 minutes in seconds; how long the access token to the server is good for 8 | DEFAULT_TTL = 600 9 | 10 | # The signing algorithm used by the {jwt} gem internals 11 | SIGNING_ALGORITHM = "HS256" 12 | 13 | attr_accessor :grants, :identity 14 | 15 | def initialize( 16 | api_key: nil, 17 | api_secret: nil, 18 | identity: nil, 19 | ttl: DEFAULT_TTL, 20 | name: nil, 21 | metadata: nil, 22 | attributes: nil 23 | ) 24 | @api_key = api_key || ENV["LIVEKIT_API_KEY"] 25 | @api_secret = api_secret || ENV["LIVEKIT_API_SECRET"] 26 | @grants = ClaimGrant.new 27 | @grants.name = name 28 | @grants.metadata = metadata 29 | @grants.attributes = attributes 30 | @identity = identity 31 | @ttl = ttl 32 | end 33 | 34 | # Deprecated, use video_grant = instead 35 | def add_grant(video_grant) 36 | if video_grant.is_a?(Hash) 37 | video_grant = VideoGrant.from_hash(video_grant) 38 | end 39 | self.video_grant = video_grant 40 | end 41 | 42 | def video_grant=(video_grant) 43 | @grants.video = video_grant 44 | end 45 | 46 | # Deprecated, use sip_grant = instead 47 | def add_sip_grant(sip_grant) 48 | if sip_grant.is_a?(Hash) 49 | sip_grant = SIPGrant.from_hash(sip_grant) 50 | end 51 | self.sip_grant = sip_grant 52 | end 53 | 54 | def sip_grant=(sip_grant) 55 | @grants.sip = sip_grant 56 | end 57 | 58 | def metadata=(participant_md) 59 | @grants.metadata = participant_md 60 | end 61 | 62 | def attributes=(participant_attributes) 63 | @grants.attributes = participant_attributes 64 | end 65 | 66 | def name=(participant_name) 67 | @grants.name = participant_name 68 | end 69 | 70 | def sha256 71 | @grants.sha256 72 | end 73 | 74 | def sha256=(sha_string) 75 | @grants.sha256 = sha_string 76 | end 77 | 78 | def room_config=(room_config) 79 | @grants.room_config = room_config 80 | end 81 | 82 | def room_preset=(room_preset) 83 | @grants.room_preset = room_preset 84 | end 85 | 86 | def to_jwt 87 | if @grants.video.nil? && @grants.sip.nil? 88 | raise ArgumentError, "VideoGrant or SIPGrant is required" 89 | end 90 | 91 | jwt_timestamp = Time.now.to_i 92 | payload = {} 93 | payload.merge!(@grants.to_hash) 94 | payload.merge!({ 95 | exp: jwt_timestamp + @ttl, 96 | nbf: jwt_timestamp - 5, 97 | iss: @api_key, 98 | sub: @identity, 99 | }) 100 | payload.compact! 101 | 102 | return JWT.encode(payload, @api_secret, SIGNING_ALGORITHM) 103 | end 104 | end 105 | end 106 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "rubygems" 12 | 13 | m = Module.new do 14 | module_function 15 | 16 | def invoked_as_script? 17 | File.expand_path($0) == File.expand_path(__FILE__) 18 | end 19 | 20 | def env_var_version 21 | ENV["BUNDLER_VERSION"] 22 | end 23 | 24 | def cli_arg_version 25 | return unless invoked_as_script? # don't want to hijack other binstubs 26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` 27 | bundler_version = nil 28 | update_index = nil 29 | ARGV.each_with_index do |a, i| 30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN 31 | bundler_version = a 32 | end 33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ 34 | bundler_version = $1 35 | update_index = i 36 | end 37 | bundler_version 38 | end 39 | 40 | def gemfile 41 | gemfile = ENV["BUNDLE_GEMFILE"] 42 | return gemfile if gemfile && !gemfile.empty? 43 | 44 | File.expand_path("../../Gemfile", __FILE__) 45 | end 46 | 47 | def lockfile 48 | lockfile = 49 | case File.basename(gemfile) 50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) 51 | else "#{gemfile}.lock" 52 | end 53 | File.expand_path(lockfile) 54 | end 55 | 56 | def lockfile_version 57 | return unless File.file?(lockfile) 58 | lockfile_contents = File.read(lockfile) 59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ 60 | Regexp.last_match(1) 61 | end 62 | 63 | def bundler_version 64 | @bundler_version ||= 65 | env_var_version || cli_arg_version || 66 | lockfile_version 67 | end 68 | 69 | def bundler_requirement 70 | return "#{Gem::Requirement.default}.a" unless bundler_version 71 | 72 | bundler_gem_version = Gem::Version.new(bundler_version) 73 | 74 | requirement = bundler_gem_version.approximate_recommendation 75 | 76 | return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") 77 | 78 | requirement += ".a" if bundler_gem_version.prerelease? 79 | 80 | requirement 81 | end 82 | 83 | def load_bundler! 84 | ENV["BUNDLE_GEMFILE"] ||= gemfile 85 | 86 | activate_bundler 87 | end 88 | 89 | def activate_bundler 90 | gem_error = activation_error_handling do 91 | gem "bundler", bundler_requirement 92 | end 93 | return if gem_error.nil? 94 | require_error = activation_error_handling do 95 | require "bundler/version" 96 | end 97 | return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) 98 | warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" 99 | exit 42 100 | end 101 | 102 | def activation_error_handling 103 | yield 104 | nil 105 | rescue StandardError, LoadError => e 106 | e 107 | end 108 | end 109 | 110 | m.load_bundler! 111 | 112 | if m.invoked_as_script? 113 | load Gem.bin_path("bundler", "bundle") 114 | end 115 | -------------------------------------------------------------------------------- /lib/livekit/agent_dispatch_service_client.rb: -------------------------------------------------------------------------------- 1 | require "livekit/proto/livekit_agent_dispatch_twirp" 2 | require "livekit/auth_mixin" 3 | require 'livekit/utils' 4 | 5 | module LiveKit 6 | # Client for LiveKit's Agent Dispatch Service, which manages agent assignments to rooms 7 | # This client handles creating, deleting, and retrieving agent dispatches 8 | class AgentDispatchServiceClient < Twirp::Client 9 | client_for Proto::AgentDispatchServiceService 10 | include AuthMixin 11 | attr_accessor :api_key, :api_secret 12 | 13 | def initialize(base_url, api_key: nil, api_secret: nil) 14 | super(File.join(Utils.to_http_url(base_url), "/twirp")) 15 | @api_key = api_key 16 | @api_secret = api_secret 17 | end 18 | 19 | # Creates a new agent dispatch for a named agent 20 | # @param room_name [String] The room to dispatch the agent to 21 | # @param agent_name [String] The name of the agent to dispatch 22 | # @param metadata [String, nil] Optional metadata to include with the dispatch 23 | # @return [LiveKit::Proto::AgentDispatch] Dispatch that was just created 24 | def create_dispatch( 25 | # room to dispatch agent to 26 | room_name, 27 | # agent to dispatch 28 | agent_name, 29 | # optional, metadata to send along with the job 30 | metadata: nil 31 | ) 32 | request = Proto::CreateAgentDispatchRequest.new( 33 | room: room_name, 34 | agent_name: agent_name, 35 | metadata: metadata, 36 | ) 37 | self.rpc( 38 | :CreateDispatch, 39 | request, 40 | headers: auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room_name)), 41 | ) 42 | end 43 | 44 | # Deletes an existing agent dispatch 45 | # @param dispatch_id [String] The ID of the dispatch to delete 46 | # @param room_name [String] The room name associated with the dispatch 47 | # @return [LiveKit::Proto::AgentDispatch] AgentDispatch record that was deleted 48 | def delete_dispatch(dispatch_id, room_name) 49 | request = Proto::DeleteAgentDispatchRequest.new( 50 | dispatch_id: dispatch_id, 51 | room: room_name, 52 | ) 53 | self.rpc( 54 | :DeleteDispatch, 55 | request, 56 | headers: auth_header(VideoGrant.new(roomAdmin: true, room: room_name)), 57 | ) 58 | end 59 | 60 | # Retrieves a specific agent dispatch by ID 61 | # @param dispatch_id [String] The ID of the dispatch to retrieve 62 | # @param room_name [String] The room name associated with the dispatch 63 | # @return [LiveKit::Proto::AgentDispatch, nil] The agent dispatch if found, nil otherwise 64 | def get_dispatch(dispatch_id, room_name) 65 | request = Proto::ListAgentDispatchRequest.new( 66 | dispatch_id: dispatch_id, 67 | room: room_name, 68 | ) 69 | res = self.rpc( 70 | :ListDispatch, 71 | request, 72 | headers: auth_header(VideoGrant.new(roomAdmin: true, room: room_name)), 73 | ) 74 | if res.agent_dispatches.size > 0 75 | return res.agent_dispatches[0] 76 | end 77 | nil 78 | end 79 | 80 | # Lists all agent dispatches for a specific room 81 | # @param room_name [String] The room name to list dispatches for 82 | # @return [Array] Array of agent dispatches 83 | def list_dispatch(room_name) 84 | request = Proto::ListAgentDispatchRequest.new( 85 | room: room_name, 86 | ) 87 | res = self.rpc( 88 | :ListDispatch, 89 | request, 90 | headers: auth_header(VideoGrant.new(roomAdmin: true, room: room_name)), 91 | ) 92 | res.agent_dispatches 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /spec/livekit/access_token_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | TEST_KEY = "API87mWmmh7KM3V" 4 | TEST_SECRET = "helOnxxeT71NeOEBcYm3kW0s1pofQAbitubCw7AIsY0A" 5 | 6 | RSpec.describe LiveKit::AccessToken do 7 | it "generates a valid JWT with defaults" do 8 | token = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET) 9 | token.video_grant = LiveKit::VideoGrant.new 10 | jwt = token.to_jwt 11 | decoded = JWT.decode(jwt, TEST_SECRET, true, algorithm: "HS256") 12 | expect(decoded.first["iss"]).to eq(TEST_KEY) 13 | end 14 | 15 | it "accepts hashes for grants" do 16 | token = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET) 17 | token.add_grant(roomCreate: true) 18 | jwt = token.to_jwt 19 | decoded = JWT.decode(jwt, TEST_SECRET, true, algorithm: "HS256").first 20 | expect(decoded["video"]["roomCreate"]).to eq(true) 21 | end 22 | 23 | it "encodes join tokens" do 24 | token = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET, 25 | identity: "test_identity", ttl: 60) 26 | token.name = "myname" 27 | token.video_grant = LiveKit::VideoGrant.new(roomJoin: true, room: "myroom", canPublish: false) 28 | jwt = token.to_jwt 29 | 30 | decoded = JWT.decode(jwt, TEST_SECRET, true, algorithm: "HS256") 31 | expect(decoded.first["name"]).to eq("myname") 32 | video_grant = decoded.first["video"] 33 | expect(video_grant["roomJoin"]).to eq(true) 34 | expect(video_grant["room"]).to eq("myroom") 35 | expect(video_grant["canPublish"]).to eq(false) 36 | end 37 | 38 | it "handles agent dispatch" do 39 | token = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET) 40 | token.video_grant = LiveKit::VideoGrant.new(roomJoin: true, room: "myroom", canPublish: false) 41 | token.room_config = LiveKit::Proto::RoomConfiguration.new( 42 | max_participants: 10, 43 | agents: [LiveKit::Proto::RoomAgentDispatch.new( 44 | agent_name: "test-agent", 45 | metadata: "test-metadata", 46 | )] 47 | ) 48 | jwt = token.to_jwt 49 | 50 | grant = LiveKit::TokenVerifier.new(api_key: TEST_KEY, api_secret: TEST_SECRET).verify(jwt) 51 | expect(grant.video.room).to eq("myroom") 52 | expect(grant.room_config.agents[0].agent_name).to eq("test-agent") 53 | expect(grant.room_config.agents[0].metadata).to eq("test-metadata") 54 | end 55 | end 56 | 57 | RSpec.describe LiveKit::ClaimGrant do 58 | it "can be converted to a hash and back" do 59 | claim_grant = described_class.new 60 | claim_grant.identity = "test_identity" 61 | claim_grant.name = "myname" 62 | claim_grant.video = LiveKit::VideoGrant.new(roomJoin: true, room: "myroom", canPublish: false) 63 | claim_grant.room_config = LiveKit::Proto::RoomConfiguration.new( 64 | max_participants: 10, 65 | agents: [LiveKit::Proto::RoomAgentDispatch.new( 66 | agent_name: "test-agent", 67 | metadata: "test-metadata", 68 | )] 69 | ) 70 | hash = claim_grant.to_hash 71 | expect(hash[:name]).to eq("myname") 72 | agents = hash[:roomConfig]["agents"] 73 | expect(agents.size).to eq(1) 74 | expect(agents[0]["agentName"]).to eq("test-agent") 75 | expect(agents[0]["metadata"]).to eq("test-metadata") 76 | 77 | serialized = hash.to_json 78 | restored = JSON.parse(serialized) 79 | 80 | grant_parsed = LiveKit::ClaimGrant.from_hash(restored) 81 | expect(grant_parsed.name).to eq("myname") 82 | expect(grant_parsed.video.room).to eq("myroom") 83 | expect(grant_parsed.room_config.max_participants).to eq(10) 84 | expect(grant_parsed.room_config.agents[0].agent_name).to eq("test-agent") 85 | expect(grant_parsed.room_config.agents[0].metadata).to eq("test-metadata") 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /spec/livekit/grants_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | RSpec.describe LiveKit::ClaimGrant do 4 | describe 'initialization' do 5 | it 'initializes with nil attributes' do 6 | claim_grant = LiveKit::ClaimGrant.new 7 | expect(claim_grant.identity).to be_nil 8 | expect(claim_grant.name).to be_nil 9 | expect(claim_grant.metadata).to be_nil 10 | expect(claim_grant.sha256).to be_nil 11 | expect(claim_grant.video).to be_nil 12 | end 13 | end 14 | 15 | describe '.from_hash' do 16 | context 'when input is valid' do 17 | let(:input_hash) do 18 | { 19 | 'sub' => '123', 20 | 'name' => 'John Doe', 21 | 'metadata' => 'User data', 22 | 'sha256' => 'hashcode', 23 | 'video' => {} 24 | } 25 | end 26 | 27 | it 'creates a ClaimGrant with proper attributes' do 28 | claim_grant = LiveKit::ClaimGrant.from_hash(input_hash) 29 | expect(claim_grant.identity).to eq('123') 30 | expect(claim_grant.name).to eq('John Doe') 31 | expect(claim_grant.metadata).to eq('User data') 32 | expect(claim_grant.sha256).to eq('hashcode') 33 | expect(claim_grant.video).to be_a(LiveKit::VideoGrant) 34 | end 35 | end 36 | 37 | context 'when input is nil' do 38 | it 'returns nil' do 39 | expect(LiveKit::ClaimGrant.from_hash(nil)).to be_nil 40 | end 41 | end 42 | 43 | context 'when input has symbol keys' do 44 | let(:input_hash_with_symbols) do 45 | { 46 | roomCreate: true, 47 | roomJoin: false, 48 | roomList: true, 49 | roomRecord: false, 50 | roomAdmin: true, 51 | "room": 'example_room', 52 | "canPublish": true, 53 | canPublishSources: ['video', 'audio'], 54 | canSubscribe: true, 55 | canPublishData: true, 56 | canUpdateOwnMetadata: false, 57 | hidden: false, 58 | recorder: true, 59 | ingressAdmin: true 60 | } 61 | end 62 | 63 | it 'creates a VideoGrant with proper attributes using symbol keys' do 64 | video_grant = LiveKit::VideoGrant.from_hash(input_hash_with_symbols) 65 | expect(video_grant.roomCreate).to eq(true) 66 | expect(video_grant.roomJoin).to eq(false) 67 | expect(video_grant.roomList).to eq(true) 68 | expect(video_grant.roomRecord).to eq(false) 69 | expect(video_grant.roomAdmin).to eq(true) 70 | expect(video_grant.room).to eq('example_room') 71 | expect(video_grant.canPublish).to eq(true) 72 | expect(video_grant.canPublishSources).to eq(['video', 'audio']) 73 | expect(video_grant.canSubscribe).to eq(true) 74 | expect(video_grant.canPublishData).to eq(true) 75 | expect(video_grant.canUpdateOwnMetadata).to eq(false) 76 | expect(video_grant.hidden).to eq(false) 77 | expect(video_grant.recorder).to eq(true) 78 | expect(video_grant.ingressAdmin).to eq(true) 79 | end 80 | end 81 | 82 | end 83 | 84 | describe '#to_hash' do 85 | it 'converts attributes to a hash correctly' do 86 | video_grant = LiveKit::VideoGrant.new 87 | claim_grant = LiveKit::ClaimGrant.new 88 | claim_grant.name = 'John Doe' 89 | claim_grant.metadata = 'User data' 90 | claim_grant.sha256 = 'hashcode' 91 | claim_grant.video = video_grant 92 | 93 | result = claim_grant.to_hash 94 | expect(result[:name]).to eq('John Doe') 95 | expect(result[:metadata]).to eq('User data') 96 | expect(result[:sha256]).to eq('hashcode') 97 | expect(result[:video]).to be_a(Hash) 98 | end 99 | end 100 | end 101 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_metrics_pb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: livekit_metrics.proto 4 | 5 | require 'google/protobuf' 6 | 7 | require 'google/protobuf/timestamp_pb' 8 | 9 | 10 | descriptor_data = "\n\x15livekit_metrics.proto\x12\x07livekit\x1a\x1fgoogle/protobuf/timestamp.proto\"\xc6\x01\n\x0cMetricsBatch\x12\x14\n\x0ctimestamp_ms\x18\x01 \x01(\x03\x12\x38\n\x14normalized_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08str_data\x18\x03 \x03(\t\x12.\n\x0btime_series\x18\x04 \x03(\x0b\x32\x19.livekit.TimeSeriesMetric\x12$\n\x06\x65vents\x18\x05 \x03(\x0b\x32\x14.livekit.EventMetric\"\x87\x01\n\x10TimeSeriesMetric\x12\r\n\x05label\x18\x01 \x01(\r\x12\x1c\n\x14participant_identity\x18\x02 \x01(\r\x12\x11\n\ttrack_sid\x18\x03 \x01(\r\x12&\n\x07samples\x18\x04 \x03(\x0b\x32\x15.livekit.MetricSample\x12\x0b\n\x03rid\x18\x05 \x01(\r\"m\n\x0cMetricSample\x12\x14\n\x0ctimestamp_ms\x18\x01 \x01(\x03\x12\x38\n\x14normalized_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\r\n\x05value\x18\x03 \x01(\x02\"\xdc\x02\n\x0b\x45ventMetric\x12\r\n\x05label\x18\x01 \x01(\r\x12\x1c\n\x14participant_identity\x18\x02 \x01(\r\x12\x11\n\ttrack_sid\x18\x03 \x01(\r\x12\x1a\n\x12start_timestamp_ms\x18\x04 \x01(\x03\x12\x1d\n\x10\x65nd_timestamp_ms\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12>\n\x1anormalized_start_timestamp\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x18normalized_end_timestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x12\x10\n\x08metadata\x18\x08 \x01(\t\x12\x0b\n\x03rid\x18\t \x01(\rB\x13\n\x11_end_timestamp_msB\x1b\n\x19_normalized_end_timestamp\"o\n\x16MetricsRecordingHeader\x12\x0f\n\x07room_id\x18\x01 \x01(\t\x12&\n\x19\x65nable_user_data_training\x18\x02 \x01(\x08H\x00\x88\x01\x01\x42\x1c\n\x1a_enable_user_data_training*\x81\x07\n\x0bMetricLabel\x12\x13\n\x0f\x41GENTS_LLM_TTFT\x10\x00\x12\x13\n\x0f\x41GENTS_STT_TTFT\x10\x01\x12\x13\n\x0f\x41GENTS_TTS_TTFB\x10\x02\x12(\n$CLIENT_VIDEO_SUBSCRIBER_FREEZE_COUNT\x10\x03\x12\x31\n-CLIENT_VIDEO_SUBSCRIBER_TOTAL_FREEZE_DURATION\x10\x04\x12\'\n#CLIENT_VIDEO_SUBSCRIBER_PAUSE_COUNT\x10\x05\x12\x31\n-CLIENT_VIDEO_SUBSCRIBER_TOTAL_PAUSES_DURATION\x10\x06\x12-\n)CLIENT_AUDIO_SUBSCRIBER_CONCEALED_SAMPLES\x10\x07\x12\x34\n0CLIENT_AUDIO_SUBSCRIBER_SILENT_CONCEALED_SAMPLES\x10\x08\x12.\n*CLIENT_AUDIO_SUBSCRIBER_CONCEALMENT_EVENTS\x10\t\x12.\n*CLIENT_AUDIO_SUBSCRIBER_INTERRUPTION_COUNT\x10\n\x12\x37\n3CLIENT_AUDIO_SUBSCRIBER_TOTAL_INTERRUPTION_DURATION\x10\x0b\x12)\n%CLIENT_SUBSCRIBER_JITTER_BUFFER_DELAY\x10\x0c\x12\x31\n-CLIENT_SUBSCRIBER_JITTER_BUFFER_EMITTED_COUNT\x10\r\x12@\n 2 | 3 | 4 | 5 | 6 | The LiveKit icon, the name of the repository and some sample code in the background. 7 | 8 | 9 | 10 | 11 | # LiveKit Server API for Ruby 12 | 13 | 14 | Use this SDK to interact with LiveKit server APIs and create access tokens from your Ruby backend. 15 | 16 | 17 | This library is designed to work with Ruby 2.6.0 and above. 18 | 19 | ## Installation 20 | 21 | Add this line to your application's Gemfile: 22 | 23 | ### Gemfile 24 | 25 | ```ruby 26 | gem 'livekit-server-sdk' 27 | ``` 28 | 29 | and then `bundle install`. 30 | 31 | ### Install system-wide 32 | 33 | ```shell 34 | gem install livekit-server-sdk 35 | ``` 36 | 37 | ## Usage 38 | 39 | ### Creating Access Tokens 40 | 41 | Creating a token for participant to join a room. 42 | 43 | ```ruby 44 | require 'livekit' 45 | 46 | token = LiveKit::AccessToken.new(api_key: 'yourkey', api_secret: 'yoursecret') 47 | token.identity = 'participant-identity' 48 | token.name = 'participant-name' 49 | token.video_grant = LiveKit::VideoGrant.new(roomJoin: true, room: 'room-name') 50 | token.attributes = { "mykey" => "myvalue" } 51 | puts token.to_jwt 52 | ``` 53 | 54 | By default, a token expires after 6 hours. You may override this by passing in `ttl` when creating the token. `ttl` is expressed in seconds. 55 | 56 | ### Setting Permissions with Access Tokens 57 | 58 | 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). 59 | 60 | ### Room Service 61 | 62 | `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. 63 | 64 | ```ruby 65 | require 'livekit' 66 | 67 | client = LiveKit::RoomServiceClient.new('https://my.livekit.instance', 68 | api_key: 'yourkey', api_secret: 'yoursecret') 69 | 70 | name = 'myroom' 71 | 72 | client.list_rooms 73 | 74 | client.list_participants(room: name) 75 | 76 | client.mute_published_track(room: name, identity: 'participant', 77 | track_sid: 'track-id', muted: true) 78 | 79 | client.remove_participant(room: name, identity: 'participant') 80 | 81 | client.delete_room(room: name) 82 | ``` 83 | 84 | ### Egress Service 85 | 86 | `EgressServiceClient` is a ruby client to EgressService. Refer to [docs](https://docs.livekit.io/guides/egress) for more usage examples 87 | 88 | ```ruby 89 | require 'livekit' 90 | 91 | # starting a room composite to S3 92 | egressClient = LiveKit::EgressServiceClient.new( 93 | "https://your-url", 94 | api_key: 'key', 95 | api_secret: 'secret' 96 | ); 97 | 98 | info = egressClient.start_room_composite_egress( 99 | 'room-name', 100 | LiveKit::Proto::EncodedFileOutput.new( 101 | file_type: LiveKit::Proto::EncodedFileType::MP4, 102 | filepath: "my-recording.mp4", 103 | s3: LiveKit::Proto::S3Upload.new( 104 | access_key: 'access-key', 105 | secret: 'secret', 106 | region: 'bucket-region', 107 | bucket: 'bucket' 108 | ) 109 | ) 110 | ) 111 | puts info 112 | 113 | # starting a track composite to RTMP 114 | urls = Google::Protobuf::RepeatedField.new(:string, ['rtmp://url1', 'rtmps://url2']) 115 | info = egressClient.start_track_composite_egress( 116 | 'room-name', 117 | LiveKit::Proto::StreamOutput.new( 118 | protocol: LiveKit::Proto::StreamProtocol::RTMP, 119 | urls: urls 120 | ), 121 | audio_track_id: 'TR_XXXXXXXXXXXX', 122 | video_track_id: 'TR_XXXXXXXXXXXX' 123 | ) 124 | puts info 125 | ``` 126 | 127 | ### Environment Variables 128 | 129 | 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: 130 | 131 | - `LIVEKIT_API_KEY` 132 | - `LIVEKIT_API_SECRET` 133 | 134 | ## License 135 | 136 | The gem is available as open source under the terms of Apache 2.0 License. 137 | 138 | 139 |
140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 |
LiveKit Ecosystem
LiveKit SDKsBrowser · iOS/macOS/visionOS · Android · Flutter · React Native · Rust · Node.js · Python · Unity · Unity (WebGL) · ESP32
Server APIsNode.js · Golang · Ruby · Java/Kotlin · Python · Rust · PHP (community) · .NET (community)
UI ComponentsReact · Android Compose · SwiftUI · Flutter
Agents FrameworksPython · Node.js · Playground
ServicesLiveKit server · Egress · Ingress · SIP
ResourcesDocs · Example apps · Cloud · Self-hosting · CLI
150 | 151 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_ingress_pb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: livekit_ingress.proto 4 | 5 | require 'google/protobuf' 6 | 7 | require 'livekit_models_pb' 8 | 9 | 10 | descriptor_data = "\n\x15livekit_ingress.proto\x12\x07livekit\x1a\x14livekit_models.proto\"\x99\x03\n\x14\x43reateIngressRequest\x12)\n\ninput_type\x18\x01 \x01(\x0e\x32\x15.livekit.IngressInput\x12\x0b\n\x03url\x18\t \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x1c\n\x14participant_identity\x18\x04 \x01(\t\x12\x18\n\x10participant_name\x18\x05 \x01(\t\x12\x1c\n\x14participant_metadata\x18\n \x01(\t\x12\x1e\n\x12\x62ypass_transcoding\x18\x08 \x01(\x08\x42\x02\x18\x01\x12\x1f\n\x12\x65nable_transcoding\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12+\n\x05\x61udio\x18\x06 \x01(\x0b\x32\x1c.livekit.IngressAudioOptions\x12+\n\x05video\x18\x07 \x01(\x0b\x32\x1c.livekit.IngressVideoOptions\x12\x14\n\x07\x65nabled\x18\x0c \x01(\x08H\x01\x88\x01\x01\x42\x15\n\x13_enable_transcodingB\n\n\x08_enabled\"\xcd\x01\n\x13IngressAudioOptions\x12\x0c\n\x04name\x18\x01 \x01(\t\x12$\n\x06source\x18\x02 \x01(\x0e\x32\x14.livekit.TrackSource\x12\x35\n\x06preset\x18\x03 \x01(\x0e\x32#.livekit.IngressAudioEncodingPresetH\x00\x12\x37\n\x07options\x18\x04 \x01(\x0b\x32$.livekit.IngressAudioEncodingOptionsH\x00\x42\x12\n\x10\x65ncoding_options\"\xcd\x01\n\x13IngressVideoOptions\x12\x0c\n\x04name\x18\x01 \x01(\t\x12$\n\x06source\x18\x02 \x01(\x0e\x32\x14.livekit.TrackSource\x12\x35\n\x06preset\x18\x03 \x01(\x0e\x32#.livekit.IngressVideoEncodingPresetH\x00\x12\x37\n\x07options\x18\x04 \x01(\x0b\x32$.livekit.IngressVideoEncodingOptionsH\x00\x42\x12\n\x10\x65ncoding_options\"\x7f\n\x1bIngressAudioEncodingOptions\x12(\n\x0b\x61udio_codec\x18\x01 \x01(\x0e\x32\x13.livekit.AudioCodec\x12\x0f\n\x07\x62itrate\x18\x02 \x01(\r\x12\x13\n\x0b\x64isable_dtx\x18\x03 \x01(\x08\x12\x10\n\x08\x63hannels\x18\x04 \x01(\r\"\x80\x01\n\x1bIngressVideoEncodingOptions\x12(\n\x0bvideo_codec\x18\x01 \x01(\x0e\x32\x13.livekit.VideoCodec\x12\x12\n\nframe_rate\x18\x02 \x01(\x01\x12#\n\x06layers\x18\x03 \x03(\x0b\x32\x13.livekit.VideoLayer\"\xf0\x03\n\x0bIngressInfo\x12\x12\n\ningress_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\nstream_key\x18\x03 \x01(\t\x12\x0b\n\x03url\x18\x04 \x01(\t\x12)\n\ninput_type\x18\x05 \x01(\x0e\x32\x15.livekit.IngressInput\x12\x1e\n\x12\x62ypass_transcoding\x18\r \x01(\x08\x42\x02\x18\x01\x12\x1f\n\x12\x65nable_transcoding\x18\x0f \x01(\x08H\x00\x88\x01\x01\x12+\n\x05\x61udio\x18\x06 \x01(\x0b\x32\x1c.livekit.IngressAudioOptions\x12+\n\x05video\x18\x07 \x01(\x0b\x32\x1c.livekit.IngressVideoOptions\x12\x11\n\troom_name\x18\x08 \x01(\t\x12\x1c\n\x14participant_identity\x18\t \x01(\t\x12\x18\n\x10participant_name\x18\n \x01(\t\x12\x1c\n\x14participant_metadata\x18\x0e \x01(\t\x12\x10\n\x08reusable\x18\x0b \x01(\x08\x12$\n\x05state\x18\x0c \x01(\x0b\x32\x15.livekit.IngressState\x12\x14\n\x07\x65nabled\x18\x10 \x01(\x08H\x01\x88\x01\x01\x42\x15\n\x13_enable_transcodingB\n\n\x08_enabled\"\x9e\x03\n\x0cIngressState\x12,\n\x06status\x18\x01 \x01(\x0e\x32\x1c.livekit.IngressState.Status\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\'\n\x05video\x18\x03 \x01(\x0b\x32\x18.livekit.InputVideoState\x12\'\n\x05\x61udio\x18\x04 \x01(\x0b\x32\x18.livekit.InputAudioState\x12\x0f\n\x07room_id\x18\x05 \x01(\t\x12\x12\n\nstarted_at\x18\x07 \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x08 \x01(\x03\x12\x12\n\nupdated_at\x18\n \x01(\x03\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12\"\n\x06tracks\x18\x06 \x03(\x0b\x32\x12.livekit.TrackInfo\"{\n\x06Status\x12\x15\n\x11\x45NDPOINT_INACTIVE\x10\x00\x12\x16\n\x12\x45NDPOINT_BUFFERING\x10\x01\x12\x17\n\x13\x45NDPOINT_PUBLISHING\x10\x02\x12\x12\n\x0e\x45NDPOINT_ERROR\x10\x03\x12\x15\n\x11\x45NDPOINT_COMPLETE\x10\x04\"o\n\x0fInputVideoState\x12\x11\n\tmime_type\x18\x01 \x01(\t\x12\x17\n\x0f\x61verage_bitrate\x18\x02 \x01(\r\x12\r\n\x05width\x18\x03 \x01(\r\x12\x0e\n\x06height\x18\x04 \x01(\r\x12\x11\n\tframerate\x18\x05 \x01(\x01\"d\n\x0fInputAudioState\x12\x11\n\tmime_type\x18\x01 \x01(\t\x12\x17\n\x0f\x61verage_bitrate\x18\x02 \x01(\r\x12\x10\n\x08\x63hannels\x18\x03 \x01(\r\x12\x13\n\x0bsample_rate\x18\x04 \x01(\r\"\x91\x03\n\x14UpdateIngressRequest\x12\x12\n\ningress_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x1c\n\x14participant_identity\x18\x04 \x01(\t\x12\x18\n\x10participant_name\x18\x05 \x01(\t\x12\x1c\n\x14participant_metadata\x18\t \x01(\t\x12#\n\x12\x62ypass_transcoding\x18\x08 \x01(\x08\x42\x02\x18\x01H\x00\x88\x01\x01\x12\x1f\n\x12\x65nable_transcoding\x18\n \x01(\x08H\x01\x88\x01\x01\x12+\n\x05\x61udio\x18\x06 \x01(\x0b\x32\x1c.livekit.IngressAudioOptions\x12+\n\x05video\x18\x07 \x01(\x0b\x32\x1c.livekit.IngressVideoOptions\x12\x14\n\x07\x65nabled\x18\x0b \x01(\x08H\x02\x88\x01\x01\x42\x15\n\x13_bypass_transcodingB\x15\n\x13_enable_transcodingB\n\n\x08_enabled\";\n\x12ListIngressRequest\x12\x11\n\troom_name\x18\x01 \x01(\t\x12\x12\n\ningress_id\x18\x02 \x01(\t\":\n\x13ListIngressResponse\x12#\n\x05items\x18\x01 \x03(\x0b\x32\x14.livekit.IngressInfo\"*\n\x14\x44\x65leteIngressRequest\x12\x12\n\ningress_id\x18\x01 \x01(\t*=\n\x0cIngressInput\x12\x0e\n\nRTMP_INPUT\x10\x00\x12\x0e\n\nWHIP_INPUT\x10\x01\x12\r\n\tURL_INPUT\x10\x02*I\n\x1aIngressAudioEncodingPreset\x12\x16\n\x12OPUS_STEREO_96KBPS\x10\x00\x12\x13\n\x0fOPUS_MONO_64KBS\x10\x01*\x84\x03\n\x1aIngressVideoEncodingPreset\x12\x1c\n\x18H264_720P_30FPS_3_LAYERS\x10\x00\x12\x1d\n\x19H264_1080P_30FPS_3_LAYERS\x10\x01\x12\x1c\n\x18H264_540P_25FPS_2_LAYERS\x10\x02\x12\x1b\n\x17H264_720P_30FPS_1_LAYER\x10\x03\x12\x1c\n\x18H264_1080P_30FPS_1_LAYER\x10\x04\x12(\n$H264_720P_30FPS_3_LAYERS_HIGH_MOTION\x10\x05\x12)\n%H264_1080P_30FPS_3_LAYERS_HIGH_MOTION\x10\x06\x12(\n$H264_540P_25FPS_2_LAYERS_HIGH_MOTION\x10\x07\x12\'\n#H264_720P_30FPS_1_LAYER_HIGH_MOTION\x10\x08\x12(\n$H264_1080P_30FPS_1_LAYER_HIGH_MOTION\x10\t2\xa5\x02\n\x07Ingress\x12\x44\n\rCreateIngress\x12\x1d.livekit.CreateIngressRequest\x1a\x14.livekit.IngressInfo\x12\x44\n\rUpdateIngress\x12\x1d.livekit.UpdateIngressRequest\x1a\x14.livekit.IngressInfo\x12H\n\x0bListIngress\x12\x1b.livekit.ListIngressRequest\x1a\x1c.livekit.ListIngressResponse\x12\x44\n\rDeleteIngress\x12\x1d.livekit.DeleteIngressRequest\x1a\x14.livekit.IngressInfoBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" 11 | 12 | pool = Google::Protobuf::DescriptorPool.generated_pool 13 | pool.add_serialized_file(descriptor_data) 14 | 15 | module LiveKit 16 | module Proto 17 | CreateIngressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateIngressRequest").msgclass 18 | IngressAudioOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressAudioOptions").msgclass 19 | IngressVideoOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressVideoOptions").msgclass 20 | IngressAudioEncodingOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressAudioEncodingOptions").msgclass 21 | IngressVideoEncodingOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressVideoEncodingOptions").msgclass 22 | IngressInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressInfo").msgclass 23 | IngressState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressState").msgclass 24 | IngressState::Status = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressState.Status").enummodule 25 | InputVideoState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.InputVideoState").msgclass 26 | InputAudioState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.InputAudioState").msgclass 27 | UpdateIngressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateIngressRequest").msgclass 28 | ListIngressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListIngressRequest").msgclass 29 | ListIngressResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListIngressResponse").msgclass 30 | DeleteIngressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DeleteIngressRequest").msgclass 31 | IngressInput = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressInput").enummodule 32 | IngressAudioEncodingPreset = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressAudioEncodingPreset").enummodule 33 | IngressVideoEncodingPreset = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.IngressVideoEncodingPreset").enummodule 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/livekit/sip_service_client.rb: -------------------------------------------------------------------------------- 1 | require "livekit/proto/livekit_sip_twirp" 2 | require "livekit/auth_mixin" 3 | require 'livekit/utils' 4 | 5 | module LiveKit 6 | class SIPServiceClient < Twirp::Client 7 | client_for Proto::SIPService 8 | include AuthMixin 9 | attr_accessor :api_key, :api_secret 10 | 11 | def initialize(base_url, api_key: nil, api_secret: nil) 12 | super(File.join(Utils.to_http_url(base_url), "/twirp")) 13 | @api_key = api_key 14 | @api_secret = api_secret 15 | end 16 | 17 | def create_sip_inbound_trunk( 18 | # name to identify the trunk 19 | name, 20 | # numbers associated with LiveKit SIP. The Trunk will only accept calls made to these numbers. 21 | numbers, 22 | # optional, metadata to attach to the trunk 23 | metadata: nil, 24 | # optional, CIDR or IPs that traffic is accepted from. 25 | allowed_addresses: nil, 26 | # CIDR or IPs that traffic is accepted from. 27 | allowed_numbers: nil, 28 | # optional, Username and password used to authenticate inbound SIP invites. 29 | auth_username: nil, 30 | auth_password: nil, 31 | # optional, include these SIP X-* headers in 200 OK responses. 32 | headers: nil, 33 | # optional, map SIP X-* headers from INVITE to SIP participant attributes. 34 | headers_to_attributes: nil, 35 | # optional, map SIP response headers from INVITE to sip.h.* participant attributes automatically. 36 | include_headers: Proto::SIPHeaderOptions::SIP_NO_HEADERS, 37 | # optional, enable Krisp for this trunk 38 | krisp_enabled: false 39 | ) 40 | request = Proto::CreateSIPInboundTrunkRequest.new( 41 | trunk: Proto::SIPInboundTrunkInfo.new( 42 | name: name, 43 | metadata: metadata, 44 | numbers: numbers, 45 | allowed_addresses: allowed_addresses, 46 | allowed_numbers: allowed_numbers, 47 | auth_username: auth_username, 48 | auth_password: auth_password, 49 | headers: headers, 50 | headers_to_attributes: headers_to_attributes, 51 | include_headers: include_headers, 52 | krisp_enabled: krisp_enabled 53 | ) 54 | ) 55 | self.rpc( 56 | :CreateSIPInboundTrunk, 57 | request, 58 | headers: auth_header(sip_grant: SIPGrant.new(admin: true)), 59 | ) 60 | end 61 | 62 | def create_sip_outbound_trunk( 63 | # name to identify the trunk 64 | name, 65 | # Hostname or IP that SIP INVITE is sent too. 66 | address, 67 | # Numbers used to make the calls. Random one from this list will be selected. 68 | numbers, 69 | # optional, metadata to attach to the trunk 70 | metadata: nil, 71 | # SIP Transport used for outbound call. 72 | transport: nil, 73 | # optional, Username and password used to authenticate inbound SIP invites. 74 | auth_username: nil, 75 | auth_password: nil, 76 | # optional, include these SIP X-* headers in 200 OK responses. 77 | headers: nil, 78 | # optional map SIP X-* headers from INVITE to SIP participant attributes. 79 | headers_to_attributes: nil 80 | ) 81 | request = Proto::CreateSIPOutboundTrunkRequest.new( 82 | trunk: Proto::SIPOutboundTrunkInfo.new( 83 | name: name, 84 | address: address, 85 | numbers: numbers, 86 | metadata: metadata, 87 | transport: transport, 88 | auth_username: auth_username, 89 | auth_password: auth_password, 90 | headers: headers, 91 | headers_to_attributes: headers_to_attributes 92 | ) 93 | ) 94 | self.rpc( 95 | :CreateSIPOutboundTrunk, 96 | request, 97 | headers: auth_header(sip_grant: SIPGrant.new(admin: true)), 98 | ) 99 | end 100 | 101 | def list_sip_inbound_trunk 102 | request = Proto::ListSIPInboundTrunkRequest.new 103 | self.rpc( 104 | :ListSIPInboundTrunk, 105 | request, 106 | headers: auth_header(sip_grant: SIPGrant.new(admin: true)), 107 | ) 108 | end 109 | 110 | def list_sip_outbound_trunk 111 | request = Proto::ListSIPOutboundTrunkRequest.new 112 | self.rpc( 113 | :ListSIPOutboundTrunk, 114 | request, 115 | headers: auth_header(sip_grant: SIPGrant.new(admin: true)), 116 | ) 117 | end 118 | 119 | def delete_sip_trunk(sip_trunk_id) 120 | request = Proto::DeleteSIPTrunkRequest.new( 121 | sip_trunk_id: sip_trunk_id, 122 | ) 123 | self.rpc( 124 | :DeleteSIPTrunk, 125 | request, 126 | headers: auth_header(sip_grant: SIPGrant.new(admin: true)), 127 | ) 128 | end 129 | 130 | def create_sip_dispatch_rule( 131 | rule, 132 | name: nil, 133 | trunk_ids: nil, 134 | inbound_numbers: nil, 135 | hide_phone_number: nil, 136 | metadata: nil, 137 | attributes: nil, 138 | room_config: nil 139 | ) 140 | request = Proto::CreateSIPDispatchRuleRequest.new( 141 | rule: rule, 142 | name: name, 143 | trunk_ids: trunk_ids, 144 | inbound_numbers: inbound_numbers, 145 | hide_phone_number: hide_phone_number, 146 | metadata: metadata, 147 | attributes: attributes, 148 | room_config: room_config, 149 | ) 150 | self.rpc( 151 | :CreateSIPDispatchRule, 152 | request, 153 | headers: auth_header(sip_grant: SIPGrant.new(admin: true)), 154 | ) 155 | end 156 | 157 | def list_sip_dispatch_rule 158 | request = Proto::ListSIPDispatchRuleRequest.new 159 | self.rpc( 160 | :ListSIPDispatchRule, 161 | request, 162 | headers: auth_header(sip_grant: SIPGrant.new(admin: true)), 163 | ) 164 | end 165 | 166 | def delete_sip_dispatch_rule(sip_dispatch_rule_id) 167 | request = Proto::DeleteSIPDispatchRuleRequest.new( 168 | sip_dispatch_rule_id: sip_dispatch_rule_id, 169 | ) 170 | self.rpc( 171 | :DeleteSIPDispatchRule, 172 | request, 173 | headers: auth_header(sip_grant: SIPGrant.new(admin: true)), 174 | ) 175 | end 176 | 177 | def create_sip_participant( 178 | sip_trunk_id, 179 | sip_call_to, 180 | room_name, 181 | # Optional SIP From number to use. If empty, trunk number is used. 182 | from_number: nil, 183 | # Optional identity of the participant in LiveKit room 184 | participant_identity: nil, 185 | # Optional name of the participant in LiveKit room 186 | participant_name: nil, 187 | # Optional metadata of the participant in LiveKit room 188 | participant_metadata: nil, 189 | # Optional, send following DTMF digits (extension codes) when making a call. 190 | # Character 'w' can be used to add a 0.5 sec delay. 191 | dtmf: nil, 192 | # Optional, play dialtone for the participant 193 | play_dialtone: false, 194 | # Optional, hide phone number from participant attributes 195 | hide_phone_number: nil, 196 | # Optional, ringing timeout in seconds 197 | ringing_timeout: nil, 198 | # Optional, max call duration in seconds 199 | max_call_duration: nil, 200 | # Optional, enable Krisp for this call 201 | krisp_enabled: false 202 | ) 203 | request = Proto::CreateSIPParticipantRequest.new( 204 | sip_trunk_id: sip_trunk_id, 205 | sip_call_to: sip_call_to, 206 | sip_number: from_number, 207 | room_name: room_name, 208 | participant_identity: participant_identity, 209 | participant_name: participant_name, 210 | participant_metadata: participant_metadata, 211 | dtmf: dtmf, 212 | play_dialtone: play_dialtone, 213 | hide_phone_number: hide_phone_number, 214 | ringing_timeout: ringing_timeout, 215 | max_call_duration: max_call_duration, 216 | krisp_enabled: krisp_enabled 217 | ) 218 | self.rpc( 219 | :CreateSIPParticipant, 220 | request, 221 | headers: auth_header(sip_grant: SIPGrant.new(call: true)), 222 | ) 223 | end 224 | 225 | def transfer_sip_participant( 226 | room_name, 227 | participant_identity, 228 | transfer_to, 229 | play_dialtone: nil 230 | ) 231 | 232 | request = Proto::TransferSIPParticipantRequest.new( 233 | room_name: room_name, 234 | participant_identity: participant_identity, 235 | transfer_to: transfer_to, 236 | play_dialtone: play_dialtone, 237 | ) 238 | self.rpc( 239 | :TransferSIPParticipant, 240 | request, 241 | headers: auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room_name), sip_grant: SIPGrant.new(call: true)), 242 | ) 243 | end 244 | end 245 | end 246 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_room_pb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: livekit_room.proto 4 | 5 | require 'google/protobuf' 6 | 7 | require 'livekit_models_pb' 8 | require 'livekit_egress_pb' 9 | require 'livekit_agent_dispatch_pb' 10 | 11 | 12 | descriptor_data = "\n\x12livekit_room.proto\x12\x07livekit\x1a\x14livekit_models.proto\x1a\x14livekit_egress.proto\x1a\x1clivekit_agent_dispatch.proto\"\xda\x02\n\x11\x43reateRoomRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0broom_preset\x18\x0c \x01(\t\x12\x15\n\rempty_timeout\x18\x02 \x01(\r\x12\x19\n\x11\x64\x65parture_timeout\x18\n \x01(\r\x12\x18\n\x10max_participants\x18\x03 \x01(\r\x12\x0f\n\x07node_id\x18\x04 \x01(\t\x12\x10\n\x08metadata\x18\x05 \x01(\t\x12#\n\x06\x65gress\x18\x06 \x01(\x0b\x32\x13.livekit.RoomEgress\x12\x19\n\x11min_playout_delay\x18\x07 \x01(\r\x12\x19\n\x11max_playout_delay\x18\x08 \x01(\r\x12\x14\n\x0csync_streams\x18\t \x01(\x08\x12\x16\n\x0ereplay_enabled\x18\r \x01(\x08\x12*\n\x06\x61gents\x18\x0e \x03(\x0b\x32\x1a.livekit.RoomAgentDispatch\"\x9e\x01\n\nRoomEgress\x12\x31\n\x04room\x18\x01 \x01(\x0b\x32#.livekit.RoomCompositeEgressRequest\x12\x33\n\x0bparticipant\x18\x03 \x01(\x0b\x32\x1e.livekit.AutoParticipantEgress\x12(\n\x06tracks\x18\x02 \x01(\x0b\x32\x18.livekit.AutoTrackEgress\";\n\tRoomAgent\x12.\n\ndispatches\x18\x01 \x03(\x0b\x32\x1a.livekit.RoomAgentDispatch\"!\n\x10ListRoomsRequest\x12\r\n\x05names\x18\x01 \x03(\t\"1\n\x11ListRoomsResponse\x12\x1c\n\x05rooms\x18\x01 \x03(\x0b\x32\r.livekit.Room\"!\n\x11\x44\x65leteRoomRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\"\x14\n\x12\x44\x65leteRoomResponse\"\'\n\x17ListParticipantsRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\"J\n\x18ListParticipantsResponse\x12.\n\x0cparticipants\x18\x01 \x03(\x0b\x32\x18.livekit.ParticipantInfo\"9\n\x17RoomParticipantIdentity\x12\x0c\n\x04room\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\"\x1b\n\x19RemoveParticipantResponse\"X\n\x14MuteRoomTrackRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x11\n\ttrack_sid\x18\x03 \x01(\t\x12\r\n\x05muted\x18\x04 \x01(\x08\":\n\x15MuteRoomTrackResponse\x12!\n\x05track\x18\x01 \x01(\x0b\x32\x12.livekit.TrackInfo\"\x88\x02\n\x18UpdateParticipantRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x10\n\x08metadata\x18\x03 \x01(\t\x12\x32\n\npermission\x18\x04 \x01(\x0b\x32\x1e.livekit.ParticipantPermission\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x45\n\nattributes\x18\x06 \x03(\x0b\x32\x31.livekit.UpdateParticipantRequest.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x9b\x01\n\x1aUpdateSubscriptionsRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntrack_sids\x18\x03 \x03(\t\x12\x11\n\tsubscribe\x18\x04 \x01(\x08\x12\x36\n\x12participant_tracks\x18\x05 \x03(\x0b\x32\x1a.livekit.ParticipantTracks\"\x1d\n\x1bUpdateSubscriptionsResponse\"\xc0\x01\n\x0fSendDataRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12&\n\x04kind\x18\x03 \x01(\x0e\x32\x18.livekit.DataPacket.Kind\x12\x1c\n\x10\x64\x65stination_sids\x18\x04 \x03(\tB\x02\x18\x01\x12\x1e\n\x16\x64\x65stination_identities\x18\x06 \x03(\t\x12\x12\n\x05topic\x18\x05 \x01(\tH\x00\x88\x01\x01\x12\r\n\x05nonce\x18\x07 \x01(\x0c\x42\x08\n\x06_topic\"\x12\n\x10SendDataResponse\";\n\x19UpdateRoomMetadataRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\x12\x10\n\x08metadata\x18\x02 \x01(\t\"\x9c\x02\n\x11RoomConfiguration\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x15\n\rempty_timeout\x18\x02 \x01(\r\x12\x19\n\x11\x64\x65parture_timeout\x18\x03 \x01(\r\x12\x18\n\x10max_participants\x18\x04 \x01(\r\x12\x10\n\x08metadata\x18\x0b \x01(\t\x12#\n\x06\x65gress\x18\x05 \x01(\x0b\x32\x13.livekit.RoomEgress\x12\x19\n\x11min_playout_delay\x18\x07 \x01(\r\x12\x19\n\x11max_playout_delay\x18\x08 \x01(\r\x12\x14\n\x0csync_streams\x18\t \x01(\x08\x12*\n\x06\x61gents\x18\n \x03(\x0b\x32\x1a.livekit.RoomAgentDispatch\"U\n\x19\x46orwardParticipantRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x18\n\x10\x64\x65stination_room\x18\x03 \x01(\t\"\x1c\n\x1a\x46orwardParticipantResponse\"R\n\x16MoveParticipantRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x18\n\x10\x64\x65stination_room\x18\x03 \x01(\t\"\x19\n\x17MoveParticipantResponse\"}\n\x11PerformRpcRequest\x12\x0c\n\x04room\x18\x01 \x01(\t\x12\x1c\n\x14\x64\x65stination_identity\x18\x02 \x01(\t\x12\x0e\n\x06method\x18\x03 \x01(\t\x12\x0f\n\x07payload\x18\x04 \x01(\t\x12\x1b\n\x13response_timeout_ms\x18\x05 \x01(\r\"%\n\x12PerformRpcResponse\x12\x0f\n\x07payload\x18\x01 \x01(\t2\xe2\x08\n\x0bRoomService\x12\x37\n\nCreateRoom\x12\x1a.livekit.CreateRoomRequest\x1a\r.livekit.Room\x12\x42\n\tListRooms\x12\x19.livekit.ListRoomsRequest\x1a\x1a.livekit.ListRoomsResponse\x12\x45\n\nDeleteRoom\x12\x1a.livekit.DeleteRoomRequest\x1a\x1b.livekit.DeleteRoomResponse\x12W\n\x10ListParticipants\x12 .livekit.ListParticipantsRequest\x1a!.livekit.ListParticipantsResponse\x12L\n\x0eGetParticipant\x12 .livekit.RoomParticipantIdentity\x1a\x18.livekit.ParticipantInfo\x12Y\n\x11RemoveParticipant\x12 .livekit.RoomParticipantIdentity\x1a\".livekit.RemoveParticipantResponse\x12S\n\x12MutePublishedTrack\x12\x1d.livekit.MuteRoomTrackRequest\x1a\x1e.livekit.MuteRoomTrackResponse\x12P\n\x11UpdateParticipant\x12!.livekit.UpdateParticipantRequest\x1a\x18.livekit.ParticipantInfo\x12`\n\x13UpdateSubscriptions\x12#.livekit.UpdateSubscriptionsRequest\x1a$.livekit.UpdateSubscriptionsResponse\x12?\n\x08SendData\x12\x18.livekit.SendDataRequest\x1a\x19.livekit.SendDataResponse\x12G\n\x12UpdateRoomMetadata\x12\".livekit.UpdateRoomMetadataRequest\x1a\r.livekit.Room\x12]\n\x12\x46orwardParticipant\x12\".livekit.ForwardParticipantRequest\x1a#.livekit.ForwardParticipantResponse\x12T\n\x0fMoveParticipant\x12\x1f.livekit.MoveParticipantRequest\x1a .livekit.MoveParticipantResponse\x12\x45\n\nPerformRpc\x12\x1a.livekit.PerformRpcRequest\x1a\x1b.livekit.PerformRpcResponseBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" 13 | 14 | pool = Google::Protobuf::DescriptorPool.generated_pool 15 | pool.add_serialized_file(descriptor_data) 16 | 17 | module LiveKit 18 | module Proto 19 | CreateRoomRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateRoomRequest").msgclass 20 | RoomEgress = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RoomEgress").msgclass 21 | RoomAgent = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RoomAgent").msgclass 22 | ListRoomsRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListRoomsRequest").msgclass 23 | ListRoomsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListRoomsResponse").msgclass 24 | DeleteRoomRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DeleteRoomRequest").msgclass 25 | DeleteRoomResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DeleteRoomResponse").msgclass 26 | ListParticipantsRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListParticipantsRequest").msgclass 27 | ListParticipantsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListParticipantsResponse").msgclass 28 | RoomParticipantIdentity = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RoomParticipantIdentity").msgclass 29 | RemoveParticipantResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RemoveParticipantResponse").msgclass 30 | MuteRoomTrackRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.MuteRoomTrackRequest").msgclass 31 | MuteRoomTrackResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.MuteRoomTrackResponse").msgclass 32 | UpdateParticipantRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateParticipantRequest").msgclass 33 | UpdateSubscriptionsRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateSubscriptionsRequest").msgclass 34 | UpdateSubscriptionsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateSubscriptionsResponse").msgclass 35 | SendDataRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SendDataRequest").msgclass 36 | SendDataResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SendDataResponse").msgclass 37 | UpdateRoomMetadataRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateRoomMetadataRequest").msgclass 38 | RoomConfiguration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RoomConfiguration").msgclass 39 | ForwardParticipantRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ForwardParticipantRequest").msgclass 40 | ForwardParticipantResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ForwardParticipantResponse").msgclass 41 | MoveParticipantRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.MoveParticipantRequest").msgclass 42 | MoveParticipantResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.MoveParticipantResponse").msgclass 43 | PerformRpcRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.PerformRpcRequest").msgclass 44 | PerformRpcResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.PerformRpcResponse").msgclass 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/livekit/egress_service_client.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "livekit/proto/livekit_egress_twirp" 4 | require "livekit/auth_mixin" 5 | require 'livekit/utils' 6 | 7 | module LiveKit 8 | class EgressServiceClient < Twirp::Client 9 | client_for Proto::EgressService 10 | include AuthMixin 11 | attr_accessor :api_key, :api_secret 12 | 13 | def initialize(base_url, api_key: nil, api_secret: nil) 14 | super(File.join(Utils.to_http_url(base_url), "/twirp")) 15 | @api_key = api_key 16 | @api_secret = api_secret 17 | end 18 | 19 | def start_room_composite_egress( 20 | room_name, 21 | # EncodedFileOutput, SegmentedFileOutput, StreamOutput, ImageOutput or array containing up to one of each 22 | output, 23 | # EncodingOptionsPreset, only one of preset or advanced could be set 24 | preset: nil, 25 | # EncodingOptions, only one of preset or advanced could be set 26 | advanced: nil, 27 | # egress template url, otherwise uses default templates 28 | custom_base_url: nil, 29 | # egress layout 30 | layout: nil, 31 | # true to record only audio 32 | audio_only: false, 33 | # true to record only video 34 | video_only: false 35 | ) 36 | request = Proto::RoomCompositeEgressRequest.new( 37 | room_name: room_name, 38 | preset: preset, 39 | advanced: advanced, 40 | layout: layout, 41 | custom_base_url: custom_base_url, 42 | audio_only: audio_only, 43 | video_only: video_only, 44 | ) 45 | self.set_output(request, output) 46 | self.rpc( 47 | :StartRoomCompositeEgress, 48 | request, 49 | headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)), 50 | ) 51 | end 52 | 53 | def start_participant_egress( 54 | room_name, 55 | identity, 56 | # EncodedFileOutput, SegmentedFileOutput, StreamOutput, ImageOutput, or array containing up to one of each 57 | output, 58 | # true to record the participant's screenshare and screenshare_audio track 59 | screen_share: false, 60 | # EncodingOptionsPreset, only one of preset or advanced could be set 61 | preset: nil, 62 | # EncodingOptions, only one of preset or advanced could be set 63 | advanced: nil 64 | ) 65 | request = Proto::ParticipantEgressRequest.new( 66 | room_name: room_name, 67 | identity: identity, 68 | screen_share: screen_share, 69 | preset: preset, 70 | advanced: advanced, 71 | ) 72 | self.set_output(request, output) 73 | self.rpc( 74 | :StartParticipantEgress, 75 | request, 76 | headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)), 77 | ) 78 | end 79 | 80 | def start_track_composite_egress( 81 | room_name, 82 | # EncodedFileOutput, SegmentedFileOutput, StreamOutput, ImageOutput, or array containing up to one of each 83 | output, 84 | # TrackID of an audio track 85 | audio_track_id: nil, 86 | # TrackID of a video track 87 | video_track_id: nil, 88 | # EncodingOptionsPreset, only one of preset or advanced could be set 89 | preset: nil, 90 | # EncodingOptions, only one of preset or advanced could be set 91 | advanced: nil 92 | ) 93 | request = Proto::TrackCompositeEgressRequest.new( 94 | room_name: room_name, 95 | preset: preset, 96 | advanced: advanced, 97 | audio_track_id: audio_track_id, 98 | video_track_id: video_track_id, 99 | ) 100 | self.set_output(request, output) 101 | self.rpc( 102 | :StartTrackCompositeEgress, 103 | request, 104 | headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)), 105 | ) 106 | end 107 | 108 | def start_track_egress( 109 | room_name, 110 | # either a DirectFileOutput - egress to storage or string - egress to WebSocket URL 111 | output, 112 | track_id 113 | ) 114 | request = Proto::TrackEgressRequest.new( 115 | room_name: room_name, 116 | track_id: track_id, 117 | ) 118 | if output.filepath 119 | request.file = output 120 | else 121 | request.websocket_url = output 122 | end 123 | self.rpc( 124 | :StartTrackEgress, 125 | request, 126 | headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)), 127 | ) 128 | end 129 | 130 | def start_web_egress( 131 | url, 132 | # EncodedFileOutput, SegmentedFileOutput, StreamOutput, ImageOutput, or array containing up to one of each 133 | output, 134 | # EncodingOptionsPreset, only one of preset or advanced could be set 135 | preset: nil, 136 | # EncodingOptions, only one of preset or advanced could be set 137 | advanced: nil, 138 | # true to record only audio 139 | audio_only: false, 140 | # true to record only video 141 | video_only: false, 142 | # true to await START_RECORDING chrome log 143 | await_start_signal: false 144 | ) 145 | request = Proto::WebEgressRequest.new( 146 | url: url, 147 | preset: preset, 148 | advanced: advanced, 149 | audio_only: audio_only, 150 | video_only: video_only, 151 | await_start_signal: await_start_signal, 152 | ) 153 | self.set_output(request, output) 154 | self.rpc( 155 | :StartWebEgress, 156 | request, 157 | headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)), 158 | ) 159 | end 160 | 161 | def update_layout(egress_id, layout) 162 | self.rpc( 163 | :UpdateLayout, 164 | Proto::UpdateLayoutRequest.new( 165 | egress_id: egress_id, 166 | layout: layout, 167 | ), 168 | headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)), 169 | ) 170 | end 171 | 172 | def update_stream(egress_id, 173 | add_output_urls: [], 174 | remove_output_urls: [] 175 | ) 176 | self.rpc( 177 | :UpdateStream, 178 | Proto::UpdateStreamRequest.new( 179 | egress_id: egress_id, 180 | add_output_urls: add_output_urls, 181 | remove_output_urls: remove_output_urls, 182 | ), 183 | headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)), 184 | ) 185 | end 186 | 187 | # list all egress or only egress for a room 188 | def list_egress( 189 | room_name: nil, 190 | egress_id: nil, 191 | active: false 192 | ) 193 | self.rpc( 194 | :ListEgress, 195 | Proto::ListEgressRequest.new( 196 | room_name: room_name, 197 | active: active, 198 | egress_id: egress_id, 199 | ), 200 | headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)), 201 | ) 202 | end 203 | 204 | def stop_egress(egress_id) 205 | self.rpc( 206 | :StopEgress, 207 | Proto::StopEgressRequest.new(egress_id: egress_id), 208 | headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)), 209 | ) 210 | end 211 | 212 | private 213 | 214 | # helper that sets output to file or stream 215 | def set_output(request, output) 216 | raise "output cannot be nil" if output.nil? 217 | # note: because we are setting the outputs fields here, instead of in the initialilzer 218 | # we'll need to use the ugly Google::Protobuf::RepeatedField wrappers instead of 219 | # a regular array 220 | if output.is_a? Array 221 | output.each do |out| 222 | if out.is_a? LiveKit::Proto::EncodedFileOutput 223 | raise "cannot add multiple file outputs" if request.file_outputs.any? 224 | request.file_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::EncodedFileOutput, [out]) 225 | elsif out.is_a? LiveKit::Proto::SegmentedFileOutput 226 | raise "cannot add multiple segmented file outputs" if request.segment_outputs.any? 227 | request.segment_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::SegmentedFileOutput, [out]) 228 | elsif out.is_a? LiveKit::Proto::StreamOutput 229 | raise "cannot add multiple stream outputs" if request.stream_outputs.any? 230 | request.stream_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::StreamOutput, [out]) 231 | elsif out.is_a? LiveKit::Proto::ImageOutput 232 | raise "cannot add multiple image outputs" if request.image_outputs.any? 233 | request.image_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::ImageOutput, [out]) 234 | end 235 | end 236 | elsif output.is_a? LiveKit::Proto::EncodedFileOutput 237 | request.file = output 238 | request.file_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::EncodedFileOutput, [output]) 239 | elsif output.is_a? LiveKit::Proto::SegmentedFileOutput 240 | request.segments = output 241 | request.segment_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::SegmentedFileOutput, [output]) 242 | elsif output.is_a? LiveKit::Proto::StreamOutput 243 | request.stream = output 244 | request.stream_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::StreamOutput, [output]) 245 | elsif output.is_a? LiveKit::Proto::ImageOutput 246 | request.image_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::ImageOutput, [output]) 247 | end 248 | end 249 | end 250 | end 251 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_egress_pb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: livekit_egress.proto 4 | 5 | require 'google/protobuf' 6 | 7 | require 'livekit_models_pb' 8 | 9 | 10 | descriptor_data = "\n\x14livekit_egress.proto\x12\x07livekit\x1a\x14livekit_models.proto\"\xa3\x05\n\x1aRoomCompositeEgressRequest\x12\x11\n\troom_name\x18\x01 \x01(\t\x12\x0e\n\x06layout\x18\x02 \x01(\t\x12\x12\n\naudio_only\x18\x03 \x01(\x08\x12*\n\x0c\x61udio_mixing\x18\x0f \x01(\x0e\x32\x14.livekit.AudioMixing\x12\x12\n\nvideo_only\x18\x04 \x01(\x08\x12\x17\n\x0f\x63ustom_base_url\x18\x05 \x01(\t\x12.\n\x04\x66ile\x18\x06 \x01(\x0b\x32\x1a.livekit.EncodedFileOutputB\x02\x18\x01H\x00\x12+\n\x06stream\x18\x07 \x01(\x0b\x32\x15.livekit.StreamOutputB\x02\x18\x01H\x00\x12\x34\n\x08segments\x18\n \x01(\x0b\x32\x1c.livekit.SegmentedFileOutputB\x02\x18\x01H\x00\x12\x30\n\x06preset\x18\x08 \x01(\x0e\x32\x1e.livekit.EncodingOptionsPresetH\x01\x12,\n\x08\x61\x64vanced\x18\t \x01(\x0b\x32\x18.livekit.EncodingOptionsH\x01\x12\x30\n\x0c\x66ile_outputs\x18\x0b \x03(\x0b\x32\x1a.livekit.EncodedFileOutput\x12-\n\x0estream_outputs\x18\x0c \x03(\x0b\x32\x15.livekit.StreamOutput\x12\x35\n\x0fsegment_outputs\x18\r \x03(\x0b\x32\x1c.livekit.SegmentedFileOutput\x12+\n\rimage_outputs\x18\x0e \x03(\x0b\x32\x14.livekit.ImageOutput\x12(\n\x08webhooks\x18\x10 \x03(\x0b\x32\x16.livekit.WebhookConfigB\x08\n\x06outputB\t\n\x07options\"\xda\x04\n\x10WebEgressRequest\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x12\n\naudio_only\x18\x02 \x01(\x08\x12\x12\n\nvideo_only\x18\x03 \x01(\x08\x12\x1a\n\x12\x61wait_start_signal\x18\x0c \x01(\x08\x12.\n\x04\x66ile\x18\x04 \x01(\x0b\x32\x1a.livekit.EncodedFileOutputB\x02\x18\x01H\x00\x12+\n\x06stream\x18\x05 \x01(\x0b\x32\x15.livekit.StreamOutputB\x02\x18\x01H\x00\x12\x34\n\x08segments\x18\x06 \x01(\x0b\x32\x1c.livekit.SegmentedFileOutputB\x02\x18\x01H\x00\x12\x30\n\x06preset\x18\x07 \x01(\x0e\x32\x1e.livekit.EncodingOptionsPresetH\x01\x12,\n\x08\x61\x64vanced\x18\x08 \x01(\x0b\x32\x18.livekit.EncodingOptionsH\x01\x12\x30\n\x0c\x66ile_outputs\x18\t \x03(\x0b\x32\x1a.livekit.EncodedFileOutput\x12-\n\x0estream_outputs\x18\n \x03(\x0b\x32\x15.livekit.StreamOutput\x12\x35\n\x0fsegment_outputs\x18\x0b \x03(\x0b\x32\x1c.livekit.SegmentedFileOutput\x12+\n\rimage_outputs\x18\r \x03(\x0b\x32\x14.livekit.ImageOutput\x12(\n\x08webhooks\x18\x0e \x03(\x0b\x32\x16.livekit.WebhookConfigB\x08\n\x06outputB\t\n\x07options\"\xaf\x03\n\x18ParticipantEgressRequest\x12\x11\n\troom_name\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x14\n\x0cscreen_share\x18\x03 \x01(\x08\x12\x30\n\x06preset\x18\x04 \x01(\x0e\x32\x1e.livekit.EncodingOptionsPresetH\x00\x12,\n\x08\x61\x64vanced\x18\x05 \x01(\x0b\x32\x18.livekit.EncodingOptionsH\x00\x12\x30\n\x0c\x66ile_outputs\x18\x06 \x03(\x0b\x32\x1a.livekit.EncodedFileOutput\x12-\n\x0estream_outputs\x18\x07 \x03(\x0b\x32\x15.livekit.StreamOutput\x12\x35\n\x0fsegment_outputs\x18\x08 \x03(\x0b\x32\x1c.livekit.SegmentedFileOutput\x12+\n\rimage_outputs\x18\t \x03(\x0b\x32\x14.livekit.ImageOutput\x12(\n\x08webhooks\x18\n \x03(\x0b\x32\x16.livekit.WebhookConfigB\t\n\x07options\"\xd7\x04\n\x1bTrackCompositeEgressRequest\x12\x11\n\troom_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61udio_track_id\x18\x02 \x01(\t\x12\x16\n\x0evideo_track_id\x18\x03 \x01(\t\x12.\n\x04\x66ile\x18\x04 \x01(\x0b\x32\x1a.livekit.EncodedFileOutputB\x02\x18\x01H\x00\x12+\n\x06stream\x18\x05 \x01(\x0b\x32\x15.livekit.StreamOutputB\x02\x18\x01H\x00\x12\x34\n\x08segments\x18\x08 \x01(\x0b\x32\x1c.livekit.SegmentedFileOutputB\x02\x18\x01H\x00\x12\x30\n\x06preset\x18\x06 \x01(\x0e\x32\x1e.livekit.EncodingOptionsPresetH\x01\x12,\n\x08\x61\x64vanced\x18\x07 \x01(\x0b\x32\x18.livekit.EncodingOptionsH\x01\x12\x30\n\x0c\x66ile_outputs\x18\x0b \x03(\x0b\x32\x1a.livekit.EncodedFileOutput\x12-\n\x0estream_outputs\x18\x0c \x03(\x0b\x32\x15.livekit.StreamOutput\x12\x35\n\x0fsegment_outputs\x18\r \x03(\x0b\x32\x1c.livekit.SegmentedFileOutput\x12+\n\rimage_outputs\x18\x0e \x03(\x0b\x32\x14.livekit.ImageOutput\x12(\n\x08webhooks\x18\x0f \x03(\x0b\x32\x16.livekit.WebhookConfigB\x08\n\x06outputB\t\n\x07options\"\xb1\x01\n\x12TrackEgressRequest\x12\x11\n\troom_name\x18\x01 \x01(\t\x12\x10\n\x08track_id\x18\x02 \x01(\t\x12)\n\x04\x66ile\x18\x03 \x01(\x0b\x32\x19.livekit.DirectFileOutputH\x00\x12\x17\n\rwebsocket_url\x18\x04 \x01(\tH\x00\x12(\n\x08webhooks\x18\x05 \x03(\x0b\x32\x16.livekit.WebhookConfigB\x08\n\x06output\"\x8e\x02\n\x11\x45ncodedFileOutput\x12+\n\tfile_type\x18\x01 \x01(\x0e\x32\x18.livekit.EncodedFileType\x12\x10\n\x08\x66ilepath\x18\x02 \x01(\t\x12\x18\n\x10\x64isable_manifest\x18\x06 \x01(\x08\x12\x1f\n\x02s3\x18\x03 \x01(\x0b\x32\x11.livekit.S3UploadH\x00\x12!\n\x03gcp\x18\x04 \x01(\x0b\x32\x12.livekit.GCPUploadH\x00\x12)\n\x05\x61zure\x18\x05 \x01(\x0b\x32\x18.livekit.AzureBlobUploadH\x00\x12\'\n\x06\x61liOSS\x18\x07 \x01(\x0b\x32\x15.livekit.AliOSSUploadH\x00\x42\x08\n\x06output\"\xa0\x03\n\x13SegmentedFileOutput\x12\x30\n\x08protocol\x18\x01 \x01(\x0e\x32\x1e.livekit.SegmentedFileProtocol\x12\x17\n\x0f\x66ilename_prefix\x18\x02 \x01(\t\x12\x15\n\rplaylist_name\x18\x03 \x01(\t\x12\x1a\n\x12live_playlist_name\x18\x0b \x01(\t\x12\x18\n\x10segment_duration\x18\x04 \x01(\r\x12\x35\n\x0f\x66ilename_suffix\x18\n \x01(\x0e\x32\x1c.livekit.SegmentedFileSuffix\x12\x18\n\x10\x64isable_manifest\x18\x08 \x01(\x08\x12\x1f\n\x02s3\x18\x05 \x01(\x0b\x32\x11.livekit.S3UploadH\x00\x12!\n\x03gcp\x18\x06 \x01(\x0b\x32\x12.livekit.GCPUploadH\x00\x12)\n\x05\x61zure\x18\x07 \x01(\x0b\x32\x18.livekit.AzureBlobUploadH\x00\x12\'\n\x06\x61liOSS\x18\t \x01(\x0b\x32\x15.livekit.AliOSSUploadH\x00\x42\x08\n\x06output\"\xe0\x01\n\x10\x44irectFileOutput\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\x12\x18\n\x10\x64isable_manifest\x18\x05 \x01(\x08\x12\x1f\n\x02s3\x18\x02 \x01(\x0b\x32\x11.livekit.S3UploadH\x00\x12!\n\x03gcp\x18\x03 \x01(\x0b\x32\x12.livekit.GCPUploadH\x00\x12)\n\x05\x61zure\x18\x04 \x01(\x0b\x32\x18.livekit.AzureBlobUploadH\x00\x12\'\n\x06\x61liOSS\x18\x06 \x01(\x0b\x32\x15.livekit.AliOSSUploadH\x00\x42\x08\n\x06output\"\xf8\x02\n\x0bImageOutput\x12\x18\n\x10\x63\x61pture_interval\x18\x01 \x01(\r\x12\r\n\x05width\x18\x02 \x01(\x05\x12\x0e\n\x06height\x18\x03 \x01(\x05\x12\x17\n\x0f\x66ilename_prefix\x18\x04 \x01(\t\x12\x31\n\x0f\x66ilename_suffix\x18\x05 \x01(\x0e\x32\x18.livekit.ImageFileSuffix\x12(\n\x0bimage_codec\x18\x06 \x01(\x0e\x32\x13.livekit.ImageCodec\x12\x18\n\x10\x64isable_manifest\x18\x07 \x01(\x08\x12\x1f\n\x02s3\x18\x08 \x01(\x0b\x32\x11.livekit.S3UploadH\x00\x12!\n\x03gcp\x18\t \x01(\x0b\x32\x12.livekit.GCPUploadH\x00\x12)\n\x05\x61zure\x18\n \x01(\x0b\x32\x18.livekit.AzureBlobUploadH\x00\x12\'\n\x06\x61liOSS\x18\x0b \x01(\x0b\x32\x15.livekit.AliOSSUploadH\x00\x42\x08\n\x06output\"\x82\x03\n\x08S3Upload\x12\x12\n\naccess_key\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\x15\n\rsession_token\x18\x0b \x01(\t\x12\x17\n\x0f\x61ssume_role_arn\x18\x0c \x01(\t\x12\x1f\n\x17\x61ssume_role_external_id\x18\r \x01(\t\x12\x0e\n\x06region\x18\x03 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x04 \x01(\t\x12\x0e\n\x06\x62ucket\x18\x05 \x01(\t\x12\x18\n\x10\x66orce_path_style\x18\x06 \x01(\x08\x12\x31\n\x08metadata\x18\x07 \x03(\x0b\x32\x1f.livekit.S3Upload.MetadataEntry\x12\x0f\n\x07tagging\x18\x08 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\t \x01(\t\x12#\n\x05proxy\x18\n \x01(\x0b\x32\x14.livekit.ProxyConfig\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\tGCPUpload\x12\x13\n\x0b\x63redentials\x18\x01 \x01(\t\x12\x0e\n\x06\x62ucket\x18\x02 \x01(\t\x12#\n\x05proxy\x18\x03 \x01(\x0b\x32\x14.livekit.ProxyConfig\"T\n\x0f\x41zureBlobUpload\x12\x14\n\x0c\x61\x63\x63ount_name\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63\x63ount_key\x18\x02 \x01(\t\x12\x16\n\x0e\x63ontainer_name\x18\x03 \x01(\t\"d\n\x0c\x41liOSSUpload\x12\x12\n\naccess_key\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\x0e\n\x06region\x18\x03 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x04 \x01(\t\x12\x0e\n\x06\x62ucket\x18\x05 \x01(\t\">\n\x0bProxyConfig\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x10\n\x08username\x18\x02 \x01(\t\x12\x10\n\x08password\x18\x03 \x01(\t\"G\n\x0cStreamOutput\x12)\n\x08protocol\x18\x01 \x01(\x0e\x32\x17.livekit.StreamProtocol\x12\x0c\n\x04urls\x18\x02 \x03(\t\"\xb7\x02\n\x0f\x45ncodingOptions\x12\r\n\x05width\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x05\x12\r\n\x05\x64\x65pth\x18\x03 \x01(\x05\x12\x11\n\tframerate\x18\x04 \x01(\x05\x12(\n\x0b\x61udio_codec\x18\x05 \x01(\x0e\x32\x13.livekit.AudioCodec\x12\x15\n\raudio_bitrate\x18\x06 \x01(\x05\x12\x15\n\raudio_quality\x18\x0b \x01(\x05\x12\x17\n\x0f\x61udio_frequency\x18\x07 \x01(\x05\x12(\n\x0bvideo_codec\x18\x08 \x01(\x0e\x32\x13.livekit.VideoCodec\x12\x15\n\rvideo_bitrate\x18\t \x01(\x05\x12\x15\n\rvideo_quality\x18\x0c \x01(\x05\x12\x1a\n\x12key_frame_interval\x18\n \x01(\x01\"8\n\x13UpdateLayoutRequest\x12\x11\n\tegress_id\x18\x01 \x01(\t\x12\x0e\n\x06layout\x18\x02 \x01(\t\"]\n\x13UpdateStreamRequest\x12\x11\n\tegress_id\x18\x01 \x01(\t\x12\x17\n\x0f\x61\x64\x64_output_urls\x18\x02 \x03(\t\x12\x1a\n\x12remove_output_urls\x18\x03 \x03(\t\"I\n\x11ListEgressRequest\x12\x11\n\troom_name\x18\x01 \x01(\t\x12\x11\n\tegress_id\x18\x02 \x01(\t\x12\x0e\n\x06\x61\x63tive\x18\x03 \x01(\x08\"8\n\x12ListEgressResponse\x12\"\n\x05items\x18\x01 \x03(\x0b\x32\x13.livekit.EgressInfo\"&\n\x11StopEgressRequest\x12\x11\n\tegress_id\x18\x01 \x01(\t\"\x9e\x07\n\nEgressInfo\x12\x11\n\tegress_id\x18\x01 \x01(\t\x12\x0f\n\x07room_id\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\r \x01(\t\x12.\n\x0bsource_type\x18\x1a \x01(\x0e\x32\x19.livekit.EgressSourceType\x12%\n\x06status\x18\x03 \x01(\x0e\x32\x15.livekit.EgressStatus\x12\x12\n\nstarted_at\x18\n \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x0b \x01(\x03\x12\x12\n\nupdated_at\x18\x12 \x01(\x03\x12\x0f\n\x07\x64\x65tails\x18\x15 \x01(\t\x12\r\n\x05\x65rror\x18\t \x01(\t\x12\x12\n\nerror_code\x18\x16 \x01(\x05\x12=\n\x0eroom_composite\x18\x04 \x01(\x0b\x32#.livekit.RoomCompositeEgressRequestH\x00\x12(\n\x03web\x18\x0e \x01(\x0b\x32\x19.livekit.WebEgressRequestH\x00\x12\x38\n\x0bparticipant\x18\x13 \x01(\x0b\x32!.livekit.ParticipantEgressRequestH\x00\x12?\n\x0ftrack_composite\x18\x05 \x01(\x0b\x32$.livekit.TrackCompositeEgressRequestH\x00\x12,\n\x05track\x18\x06 \x01(\x0b\x32\x1b.livekit.TrackEgressRequestH\x00\x12-\n\x06stream\x18\x07 \x01(\x0b\x32\x17.livekit.StreamInfoListB\x02\x18\x01H\x01\x12%\n\x04\x66ile\x18\x08 \x01(\x0b\x32\x11.livekit.FileInfoB\x02\x18\x01H\x01\x12-\n\x08segments\x18\x0c \x01(\x0b\x32\x15.livekit.SegmentsInfoB\x02\x18\x01H\x01\x12+\n\x0estream_results\x18\x0f \x03(\x0b\x32\x13.livekit.StreamInfo\x12\'\n\x0c\x66ile_results\x18\x10 \x03(\x0b\x32\x11.livekit.FileInfo\x12.\n\x0fsegment_results\x18\x11 \x03(\x0b\x32\x15.livekit.SegmentsInfo\x12*\n\rimage_results\x18\x14 \x03(\x0b\x32\x13.livekit.ImagesInfo\x12\x19\n\x11manifest_location\x18\x17 \x01(\t\x12\x1b\n\x13\x62\x61\x63kup_storage_used\x18\x19 \x01(\x08\x42\t\n\x07requestB\x08\n\x06result\"7\n\x0eStreamInfoList\x12!\n\x04info\x18\x01 \x03(\x0b\x32\x13.livekit.StreamInfo:\x02\x18\x01\"\xbc\x01\n\nStreamInfo\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x12\n\nstarted_at\x18\x02 \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x03 \x01(\x03\x12\x10\n\x08\x64uration\x18\x04 \x01(\x03\x12*\n\x06status\x18\x05 \x01(\x0e\x32\x1a.livekit.StreamInfo.Status\x12\r\n\x05\x65rror\x18\x06 \x01(\t\".\n\x06Status\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\x0c\n\x08\x46INISHED\x10\x01\x12\n\n\x06\x46\x41ILED\x10\x02\"t\n\x08\x46ileInfo\x12\x10\n\x08\x66ilename\x18\x01 \x01(\t\x12\x12\n\nstarted_at\x18\x02 \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x03 \x01(\x03\x12\x10\n\x08\x64uration\x18\x06 \x01(\x03\x12\x0c\n\x04size\x18\x04 \x01(\x03\x12\x10\n\x08location\x18\x05 \x01(\t\"\xd9\x01\n\x0cSegmentsInfo\x12\x15\n\rplaylist_name\x18\x01 \x01(\t\x12\x1a\n\x12live_playlist_name\x18\x08 \x01(\t\x12\x10\n\x08\x64uration\x18\x02 \x01(\x03\x12\x0c\n\x04size\x18\x03 \x01(\x03\x12\x19\n\x11playlist_location\x18\x04 \x01(\t\x12\x1e\n\x16live_playlist_location\x18\t \x01(\t\x12\x15\n\rsegment_count\x18\x05 \x01(\x03\x12\x12\n\nstarted_at\x18\x06 \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x07 \x01(\x03\"`\n\nImagesInfo\x12\x17\n\x0f\x66ilename_prefix\x18\x04 \x01(\t\x12\x13\n\x0bimage_count\x18\x01 \x01(\x03\x12\x12\n\nstarted_at\x18\x02 \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x03 \x01(\x03\"\xeb\x01\n\x15\x41utoParticipantEgress\x12\x30\n\x06preset\x18\x01 \x01(\x0e\x32\x1e.livekit.EncodingOptionsPresetH\x00\x12,\n\x08\x61\x64vanced\x18\x02 \x01(\x0b\x32\x18.livekit.EncodingOptionsH\x00\x12\x30\n\x0c\x66ile_outputs\x18\x03 \x03(\x0b\x32\x1a.livekit.EncodedFileOutput\x12\x35\n\x0fsegment_outputs\x18\x04 \x03(\x0b\x32\x1c.livekit.SegmentedFileOutputB\t\n\x07options\"\xdf\x01\n\x0f\x41utoTrackEgress\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\x12\x18\n\x10\x64isable_manifest\x18\x05 \x01(\x08\x12\x1f\n\x02s3\x18\x02 \x01(\x0b\x32\x11.livekit.S3UploadH\x00\x12!\n\x03gcp\x18\x03 \x01(\x0b\x32\x12.livekit.GCPUploadH\x00\x12)\n\x05\x61zure\x18\x04 \x01(\x0b\x32\x18.livekit.AzureBlobUploadH\x00\x12\'\n\x06\x61liOSS\x18\x06 \x01(\x0b\x32\x15.livekit.AliOSSUploadH\x00\x42\x08\n\x06output*B\n\x0f\x45ncodedFileType\x12\x14\n\x10\x44\x45\x46\x41ULT_FILETYPE\x10\x00\x12\x07\n\x03MP4\x10\x01\x12\x07\n\x03OGG\x10\x02\x12\x07\n\x03MP3\x10\x03*N\n\x15SegmentedFileProtocol\x12#\n\x1f\x44\x45\x46\x41ULT_SEGMENTED_FILE_PROTOCOL\x10\x00\x12\x10\n\x0cHLS_PROTOCOL\x10\x01*/\n\x13SegmentedFileSuffix\x12\t\n\x05INDEX\x10\x00\x12\r\n\tTIMESTAMP\x10\x01*f\n\x0fImageFileSuffix\x12\x16\n\x12IMAGE_SUFFIX_INDEX\x10\x00\x12\x1a\n\x16IMAGE_SUFFIX_TIMESTAMP\x10\x01\x12\x1f\n\x1bIMAGE_SUFFIX_NONE_OVERWRITE\x10\x02*9\n\x0eStreamProtocol\x12\x14\n\x10\x44\x45\x46\x41ULT_PROTOCOL\x10\x00\x12\x08\n\x04RTMP\x10\x01\x12\x07\n\x03SRT\x10\x02*U\n\x0b\x41udioMixing\x12\x12\n\x0e\x44\x45\x46\x41ULT_MIXING\x10\x00\x12\x16\n\x12\x44UAL_CHANNEL_AGENT\x10\x01\x12\x1a\n\x16\x44UAL_CHANNEL_ALTERNATE\x10\x02*\xcf\x01\n\x15\x45ncodingOptionsPreset\x12\x10\n\x0cH264_720P_30\x10\x00\x12\x10\n\x0cH264_720P_60\x10\x01\x12\x11\n\rH264_1080P_30\x10\x02\x12\x11\n\rH264_1080P_60\x10\x03\x12\x19\n\x15PORTRAIT_H264_720P_30\x10\x04\x12\x19\n\x15PORTRAIT_H264_720P_60\x10\x05\x12\x1a\n\x16PORTRAIT_H264_1080P_30\x10\x06\x12\x1a\n\x16PORTRAIT_H264_1080P_60\x10\x07*\x9f\x01\n\x0c\x45gressStatus\x12\x13\n\x0f\x45GRESS_STARTING\x10\x00\x12\x11\n\rEGRESS_ACTIVE\x10\x01\x12\x11\n\rEGRESS_ENDING\x10\x02\x12\x13\n\x0f\x45GRESS_COMPLETE\x10\x03\x12\x11\n\rEGRESS_FAILED\x10\x04\x12\x12\n\x0e\x45GRESS_ABORTED\x10\x05\x12\x18\n\x14\x45GRESS_LIMIT_REACHED\x10\x06*J\n\x10\x45gressSourceType\x12\x1a\n\x16\x45GRESS_SOURCE_TYPE_WEB\x10\x00\x12\x1a\n\x16\x45GRESS_SOURCE_TYPE_SDK\x10\x01\x32\x9c\x05\n\x06\x45gress\x12T\n\x18StartRoomCompositeEgress\x12#.livekit.RoomCompositeEgressRequest\x1a\x13.livekit.EgressInfo\x12@\n\x0eStartWebEgress\x12\x19.livekit.WebEgressRequest\x1a\x13.livekit.EgressInfo\x12P\n\x16StartParticipantEgress\x12!.livekit.ParticipantEgressRequest\x1a\x13.livekit.EgressInfo\x12V\n\x19StartTrackCompositeEgress\x12$.livekit.TrackCompositeEgressRequest\x1a\x13.livekit.EgressInfo\x12\x44\n\x10StartTrackEgress\x12\x1b.livekit.TrackEgressRequest\x1a\x13.livekit.EgressInfo\x12\x41\n\x0cUpdateLayout\x12\x1c.livekit.UpdateLayoutRequest\x1a\x13.livekit.EgressInfo\x12\x41\n\x0cUpdateStream\x12\x1c.livekit.UpdateStreamRequest\x1a\x13.livekit.EgressInfo\x12\x45\n\nListEgress\x12\x1a.livekit.ListEgressRequest\x1a\x1b.livekit.ListEgressResponse\x12=\n\nStopEgress\x12\x1a.livekit.StopEgressRequest\x1a\x13.livekit.EgressInfoBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" 11 | 12 | pool = Google::Protobuf::DescriptorPool.generated_pool 13 | pool.add_serialized_file(descriptor_data) 14 | 15 | module LiveKit 16 | module Proto 17 | RoomCompositeEgressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RoomCompositeEgressRequest").msgclass 18 | WebEgressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.WebEgressRequest").msgclass 19 | ParticipantEgressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantEgressRequest").msgclass 20 | TrackCompositeEgressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TrackCompositeEgressRequest").msgclass 21 | TrackEgressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TrackEgressRequest").msgclass 22 | EncodedFileOutput = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EncodedFileOutput").msgclass 23 | SegmentedFileOutput = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SegmentedFileOutput").msgclass 24 | DirectFileOutput = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DirectFileOutput").msgclass 25 | ImageOutput = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ImageOutput").msgclass 26 | S3Upload = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.S3Upload").msgclass 27 | GCPUpload = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.GCPUpload").msgclass 28 | AzureBlobUpload = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AzureBlobUpload").msgclass 29 | AliOSSUpload = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AliOSSUpload").msgclass 30 | ProxyConfig = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ProxyConfig").msgclass 31 | StreamOutput = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.StreamOutput").msgclass 32 | EncodingOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EncodingOptions").msgclass 33 | UpdateLayoutRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateLayoutRequest").msgclass 34 | UpdateStreamRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateStreamRequest").msgclass 35 | ListEgressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListEgressRequest").msgclass 36 | ListEgressResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListEgressResponse").msgclass 37 | StopEgressRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.StopEgressRequest").msgclass 38 | EgressInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EgressInfo").msgclass 39 | StreamInfoList = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.StreamInfoList").msgclass 40 | StreamInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.StreamInfo").msgclass 41 | StreamInfo::Status = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.StreamInfo.Status").enummodule 42 | FileInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.FileInfo").msgclass 43 | SegmentsInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SegmentsInfo").msgclass 44 | ImagesInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ImagesInfo").msgclass 45 | AutoParticipantEgress = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AutoParticipantEgress").msgclass 46 | AutoTrackEgress = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AutoTrackEgress").msgclass 47 | EncodedFileType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EncodedFileType").enummodule 48 | SegmentedFileProtocol = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SegmentedFileProtocol").enummodule 49 | SegmentedFileSuffix = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SegmentedFileSuffix").enummodule 50 | ImageFileSuffix = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ImageFileSuffix").enummodule 51 | StreamProtocol = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.StreamProtocol").enummodule 52 | AudioMixing = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AudioMixing").enummodule 53 | EncodingOptionsPreset = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EncodingOptionsPreset").enummodule 54 | EgressStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EgressStatus").enummodule 55 | EgressSourceType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EgressSourceType").enummodule 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_sip_pb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: livekit_sip.proto 4 | 5 | require 'google/protobuf' 6 | 7 | require 'google/protobuf/any_pb' 8 | require 'google/protobuf/duration_pb' 9 | require 'google/protobuf/empty_pb' 10 | require 'livekit_models_pb' 11 | require 'livekit_room_pb' 12 | 13 | 14 | descriptor_data = "\n\x11livekit_sip.proto\x12\x07livekit\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x14livekit_models.proto\x1a\x12livekit_room.proto\"A\n\tSIPStatus\x12$\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x16.livekit.SIPStatusCode\x12\x0e\n\x06status\x18\x02 \x01(\t\"\xaf\x02\n\x15\x43reateSIPTrunkRequest\x12\x19\n\x11inbound_addresses\x18\x01 \x03(\t\x12\x18\n\x10outbound_address\x18\x02 \x01(\t\x12\x17\n\x0foutbound_number\x18\x03 \x01(\t\x12!\n\x15inbound_numbers_regex\x18\x04 \x03(\tB\x02\x18\x01\x12\x17\n\x0finbound_numbers\x18\t \x03(\t\x12\x18\n\x10inbound_username\x18\x05 \x01(\t\x12\x18\n\x10inbound_password\x18\x06 \x01(\t\x12\x19\n\x11outbound_username\x18\x07 \x01(\t\x12\x19\n\x11outbound_password\x18\x08 \x01(\t\x12\x0c\n\x04name\x18\n \x01(\t\x12\x10\n\x08metadata\x18\x0b \x01(\t:\x02\x18\x01\"\xdb\x03\n\x0cSIPTrunkInfo\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12-\n\x04kind\x18\x0e \x01(\x0e\x32\x1f.livekit.SIPTrunkInfo.TrunkKind\x12\x19\n\x11inbound_addresses\x18\x02 \x03(\t\x12\x18\n\x10outbound_address\x18\x03 \x01(\t\x12\x17\n\x0foutbound_number\x18\x04 \x01(\t\x12(\n\ttransport\x18\r \x01(\x0e\x32\x15.livekit.SIPTransport\x12!\n\x15inbound_numbers_regex\x18\x05 \x03(\tB\x02\x18\x01\x12\x17\n\x0finbound_numbers\x18\n \x03(\t\x12\x18\n\x10inbound_username\x18\x06 \x01(\t\x12\x18\n\x10inbound_password\x18\x07 \x01(\t\x12\x19\n\x11outbound_username\x18\x08 \x01(\t\x12\x19\n\x11outbound_password\x18\t \x01(\t\x12\x0c\n\x04name\x18\x0b \x01(\t\x12\x10\n\x08metadata\x18\x0c \x01(\t\"D\n\tTrunkKind\x12\x10\n\x0cTRUNK_LEGACY\x10\x00\x12\x11\n\rTRUNK_INBOUND\x10\x01\x12\x12\n\x0eTRUNK_OUTBOUND\x10\x02:\x02\x18\x01\"K\n\x1c\x43reateSIPInboundTrunkRequest\x12+\n\x05trunk\x18\x01 \x01(\x0b\x32\x1c.livekit.SIPInboundTrunkInfo\"\xa1\x01\n\x1cUpdateSIPInboundTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12/\n\x07replace\x18\x02 \x01(\x0b\x32\x1c.livekit.SIPInboundTrunkInfoH\x00\x12\x30\n\x06update\x18\x03 \x01(\x0b\x32\x1e.livekit.SIPInboundTrunkUpdateH\x00\x42\x08\n\x06\x61\x63tion\"\xba\x06\n\x13SIPInboundTrunkInfo\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08metadata\x18\x03 \x01(\t\x12\x0f\n\x07numbers\x18\x04 \x03(\t\x12\x19\n\x11\x61llowed_addresses\x18\x05 \x03(\t\x12\x17\n\x0f\x61llowed_numbers\x18\x06 \x03(\t\x12\x15\n\rauth_username\x18\x07 \x01(\t\x12\x15\n\rauth_password\x18\x08 \x01(\t\x12:\n\x07headers\x18\t \x03(\x0b\x32).livekit.SIPInboundTrunkInfo.HeadersEntry\x12T\n\x15headers_to_attributes\x18\n \x03(\x0b\x32\x35.livekit.SIPInboundTrunkInfo.HeadersToAttributesEntry\x12T\n\x15\x61ttributes_to_headers\x18\x0e \x03(\x0b\x32\x35.livekit.SIPInboundTrunkInfo.AttributesToHeadersEntry\x12\x32\n\x0finclude_headers\x18\x0f \x01(\x0e\x32\x19.livekit.SIPHeaderOptions\x12\x32\n\x0fringing_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11max_call_duration\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x15\n\rkrisp_enabled\x18\r \x01(\x08\x12\x35\n\x10media_encryption\x18\x10 \x01(\x0e\x32\x1b.livekit.SIPMediaEncryption\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a:\n\x18HeadersToAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a:\n\x18\x41ttributesToHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x88\x03\n\x15SIPInboundTrunkUpdate\x12$\n\x07numbers\x18\x01 \x01(\x0b\x32\x13.livekit.ListUpdate\x12.\n\x11\x61llowed_addresses\x18\x02 \x01(\x0b\x32\x13.livekit.ListUpdate\x12,\n\x0f\x61llowed_numbers\x18\x03 \x01(\x0b\x32\x13.livekit.ListUpdate\x12\x1a\n\rauth_username\x18\x04 \x01(\tH\x00\x88\x01\x01\x12\x1a\n\rauth_password\x18\x05 \x01(\tH\x01\x88\x01\x01\x12\x11\n\x04name\x18\x06 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08metadata\x18\x07 \x01(\tH\x03\x88\x01\x01\x12:\n\x10media_encryption\x18\x08 \x01(\x0e\x32\x1b.livekit.SIPMediaEncryptionH\x04\x88\x01\x01\x42\x10\n\x0e_auth_usernameB\x10\n\x0e_auth_passwordB\x07\n\x05_nameB\x0b\n\t_metadataB\x13\n\x11_media_encryption\"M\n\x1d\x43reateSIPOutboundTrunkRequest\x12,\n\x05trunk\x18\x01 \x01(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"\xa4\x01\n\x1dUpdateSIPOutboundTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12\x30\n\x07replace\x18\x02 \x01(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfoH\x00\x12\x31\n\x06update\x18\x03 \x01(\x0b\x32\x1f.livekit.SIPOutboundTrunkUpdateH\x00\x42\x08\n\x06\x61\x63tion\"\xe1\x05\n\x14SIPOutboundTrunkInfo\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08metadata\x18\x03 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x04 \x01(\t\x12\x1b\n\x13\x64\x65stination_country\x18\x0e \x01(\t\x12(\n\ttransport\x18\x05 \x01(\x0e\x32\x15.livekit.SIPTransport\x12\x0f\n\x07numbers\x18\x06 \x03(\t\x12\x15\n\rauth_username\x18\x07 \x01(\t\x12\x15\n\rauth_password\x18\x08 \x01(\t\x12;\n\x07headers\x18\t \x03(\x0b\x32*.livekit.SIPOutboundTrunkInfo.HeadersEntry\x12U\n\x15headers_to_attributes\x18\n \x03(\x0b\x32\x36.livekit.SIPOutboundTrunkInfo.HeadersToAttributesEntry\x12U\n\x15\x61ttributes_to_headers\x18\x0b \x03(\x0b\x32\x36.livekit.SIPOutboundTrunkInfo.AttributesToHeadersEntry\x12\x32\n\x0finclude_headers\x18\x0c \x01(\x0e\x32\x19.livekit.SIPHeaderOptions\x12\x35\n\x10media_encryption\x18\r \x01(\x0e\x32\x1b.livekit.SIPMediaEncryption\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a:\n\x18HeadersToAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a:\n\x18\x41ttributesToHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xc4\x03\n\x16SIPOutboundTrunkUpdate\x12\x14\n\x07\x61\x64\x64ress\x18\x01 \x01(\tH\x00\x88\x01\x01\x12-\n\ttransport\x18\x02 \x01(\x0e\x32\x15.livekit.SIPTransportH\x01\x88\x01\x01\x12 \n\x13\x64\x65stination_country\x18\t \x01(\tH\x02\x88\x01\x01\x12$\n\x07numbers\x18\x03 \x01(\x0b\x32\x13.livekit.ListUpdate\x12\x1a\n\rauth_username\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1a\n\rauth_password\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x11\n\x04name\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x15\n\x08metadata\x18\x07 \x01(\tH\x06\x88\x01\x01\x12:\n\x10media_encryption\x18\x08 \x01(\x0e\x32\x1b.livekit.SIPMediaEncryptionH\x07\x88\x01\x01\x42\n\n\x08_addressB\x0c\n\n_transportB\x16\n\x14_destination_countryB\x10\n\x0e_auth_usernameB\x10\n\x0e_auth_passwordB\x07\n\x05_nameB\x0b\n\t_metadataB\x13\n\x11_media_encryption\"1\n\x19GetSIPInboundTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\"I\n\x1aGetSIPInboundTrunkResponse\x12+\n\x05trunk\x18\x01 \x01(\x0b\x32\x1c.livekit.SIPInboundTrunkInfo\"2\n\x1aGetSIPOutboundTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\"K\n\x1bGetSIPOutboundTrunkResponse\x12,\n\x05trunk\x18\x01 \x01(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"<\n\x13ListSIPTrunkRequest\x12!\n\x04page\x18\x01 \x01(\x0b\x32\x13.livekit.Pagination:\x02\x18\x01\"@\n\x14ListSIPTrunkResponse\x12$\n\x05items\x18\x01 \x03(\x0b\x32\x15.livekit.SIPTrunkInfo:\x02\x18\x01\"c\n\x1aListSIPInboundTrunkRequest\x12!\n\x04page\x18\x03 \x01(\x0b\x32\x13.livekit.Pagination\x12\x11\n\ttrunk_ids\x18\x01 \x03(\t\x12\x0f\n\x07numbers\x18\x02 \x03(\t\"J\n\x1bListSIPInboundTrunkResponse\x12+\n\x05items\x18\x01 \x03(\x0b\x32\x1c.livekit.SIPInboundTrunkInfo\"d\n\x1bListSIPOutboundTrunkRequest\x12!\n\x04page\x18\x03 \x01(\x0b\x32\x13.livekit.Pagination\x12\x11\n\ttrunk_ids\x18\x01 \x03(\t\x12\x0f\n\x07numbers\x18\x02 \x03(\t\"L\n\x1cListSIPOutboundTrunkResponse\x12,\n\x05items\x18\x01 \x03(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"-\n\x15\x44\x65leteSIPTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\"7\n\x15SIPDispatchRuleDirect\x12\x11\n\troom_name\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\"=\n\x19SIPDispatchRuleIndividual\x12\x13\n\x0broom_prefix\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\"L\n\x15SIPDispatchRuleCallee\x12\x13\n\x0broom_prefix\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\x12\x11\n\trandomize\x18\x03 \x01(\x08\"\xe1\x01\n\x0fSIPDispatchRule\x12>\n\x14\x64ispatch_rule_direct\x18\x01 \x01(\x0b\x32\x1e.livekit.SIPDispatchRuleDirectH\x00\x12\x46\n\x18\x64ispatch_rule_individual\x18\x02 \x01(\x0b\x32\".livekit.SIPDispatchRuleIndividualH\x00\x12>\n\x14\x64ispatch_rule_callee\x18\x03 \x01(\x0b\x32\x1e.livekit.SIPDispatchRuleCalleeH\x00\x42\x06\n\x04rule\"\xca\x03\n\x1c\x43reateSIPDispatchRuleRequest\x12\x33\n\rdispatch_rule\x18\n \x01(\x0b\x32\x1c.livekit.SIPDispatchRuleInfo\x12*\n\x04rule\x18\x01 \x01(\x0b\x32\x18.livekit.SIPDispatchRuleB\x02\x18\x01\x12\x15\n\ttrunk_ids\x18\x02 \x03(\tB\x02\x18\x01\x12\x1d\n\x11hide_phone_number\x18\x03 \x01(\x08\x42\x02\x18\x01\x12\x1b\n\x0finbound_numbers\x18\x06 \x03(\tB\x02\x18\x01\x12\x10\n\x04name\x18\x04 \x01(\tB\x02\x18\x01\x12\x14\n\x08metadata\x18\x05 \x01(\tB\x02\x18\x01\x12M\n\nattributes\x18\x07 \x03(\x0b\x32\x35.livekit.CreateSIPDispatchRuleRequest.AttributesEntryB\x02\x18\x01\x12\x17\n\x0broom_preset\x18\x08 \x01(\tB\x02\x18\x01\x12\x33\n\x0broom_config\x18\t \x01(\x0b\x32\x1a.livekit.RoomConfigurationB\x02\x18\x01\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xa9\x01\n\x1cUpdateSIPDispatchRuleRequest\x12\x1c\n\x14sip_dispatch_rule_id\x18\x01 \x01(\t\x12/\n\x07replace\x18\x02 \x01(\x0b\x32\x1c.livekit.SIPDispatchRuleInfoH\x00\x12\x30\n\x06update\x18\x03 \x01(\x0b\x32\x1e.livekit.SIPDispatchRuleUpdateH\x00\x42\x08\n\x06\x61\x63tion\"\xcb\x03\n\x13SIPDispatchRuleInfo\x12\x1c\n\x14sip_dispatch_rule_id\x18\x01 \x01(\t\x12&\n\x04rule\x18\x02 \x01(\x0b\x32\x18.livekit.SIPDispatchRule\x12\x11\n\ttrunk_ids\x18\x03 \x03(\t\x12\x19\n\x11hide_phone_number\x18\x04 \x01(\x08\x12\x17\n\x0finbound_numbers\x18\x07 \x03(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x10\n\x08metadata\x18\x06 \x01(\t\x12@\n\nattributes\x18\x08 \x03(\x0b\x32,.livekit.SIPDispatchRuleInfo.AttributesEntry\x12\x13\n\x0broom_preset\x18\t \x01(\t\x12/\n\x0broom_config\x18\n \x01(\x0b\x32\x1a.livekit.RoomConfiguration\x12\x15\n\rkrisp_enabled\x18\x0b \x01(\x08\x12\x35\n\x10media_encryption\x18\x0c \x01(\x0e\x32\x1b.livekit.SIPMediaEncryption\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xef\x02\n\x15SIPDispatchRuleUpdate\x12&\n\ttrunk_ids\x18\x01 \x01(\x0b\x32\x13.livekit.ListUpdate\x12&\n\x04rule\x18\x02 \x01(\x0b\x32\x18.livekit.SIPDispatchRule\x12\x11\n\x04name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08metadata\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x42\n\nattributes\x18\x05 \x03(\x0b\x32..livekit.SIPDispatchRuleUpdate.AttributesEntry\x12:\n\x10media_encryption\x18\x06 \x01(\x0e\x32\x1b.livekit.SIPMediaEncryptionH\x02\x88\x01\x01\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x07\n\x05_nameB\x0b\n\t_metadataB\x13\n\x11_media_encryption\"m\n\x1aListSIPDispatchRuleRequest\x12!\n\x04page\x18\x03 \x01(\x0b\x32\x13.livekit.Pagination\x12\x19\n\x11\x64ispatch_rule_ids\x18\x01 \x03(\t\x12\x11\n\ttrunk_ids\x18\x02 \x03(\t\"J\n\x1bListSIPDispatchRuleResponse\x12+\n\x05items\x18\x01 \x03(\x0b\x32\x1c.livekit.SIPDispatchRuleInfo\"<\n\x1c\x44\x65leteSIPDispatchRuleRequest\x12\x1c\n\x14sip_dispatch_rule_id\x18\x01 \x01(\t\"\xba\x03\n\x11SIPOutboundConfig\x12\x10\n\x08hostname\x18\x01 \x01(\t\x12\x1b\n\x13\x64\x65stination_country\x18\x07 \x01(\t\x12(\n\ttransport\x18\x02 \x01(\x0e\x32\x15.livekit.SIPTransport\x12\x15\n\rauth_username\x18\x03 \x01(\t\x12\x15\n\rauth_password\x18\x04 \x01(\t\x12R\n\x15headers_to_attributes\x18\x05 \x03(\x0b\x32\x33.livekit.SIPOutboundConfig.HeadersToAttributesEntry\x12R\n\x15\x61ttributes_to_headers\x18\x06 \x03(\x0b\x32\x33.livekit.SIPOutboundConfig.AttributesToHeadersEntry\x1a:\n\x18HeadersToAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a:\n\x18\x41ttributesToHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x93\x07\n\x1b\x43reateSIPParticipantRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12)\n\x05trunk\x18\x14 \x01(\x0b\x32\x1a.livekit.SIPOutboundConfig\x12\x13\n\x0bsip_call_to\x18\x02 \x01(\t\x12\x12\n\nsip_number\x18\x0f \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x1c\n\x14participant_identity\x18\x04 \x01(\t\x12\x18\n\x10participant_name\x18\x07 \x01(\t\x12\x1c\n\x14participant_metadata\x18\x08 \x01(\t\x12_\n\x16participant_attributes\x18\t \x03(\x0b\x32?.livekit.CreateSIPParticipantRequest.ParticipantAttributesEntry\x12\x0c\n\x04\x64tmf\x18\x05 \x01(\t\x12\x19\n\rplay_ringtone\x18\x06 \x01(\x08\x42\x02\x18\x01\x12\x15\n\rplay_dialtone\x18\r \x01(\x08\x12\x19\n\x11hide_phone_number\x18\n \x01(\x08\x12\x42\n\x07headers\x18\x10 \x03(\x0b\x32\x31.livekit.CreateSIPParticipantRequest.HeadersEntry\x12\x32\n\x0finclude_headers\x18\x11 \x01(\x0e\x32\x19.livekit.SIPHeaderOptions\x12\x32\n\x0fringing_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11max_call_duration\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x15\n\rkrisp_enabled\x18\x0e \x01(\x08\x12\x35\n\x10media_encryption\x18\x12 \x01(\x0e\x32\x1b.livekit.SIPMediaEncryption\x12\x1b\n\x13wait_until_answered\x18\x13 \x01(\x08\x12\x19\n\x0c\x64isplay_name\x18\x15 \x01(\tH\x00\x88\x01\x01\x1a<\n\x1aParticipantAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0f\n\r_display_name\"r\n\x12SIPParticipantInfo\x12\x16\n\x0eparticipant_id\x18\x01 \x01(\t\x12\x1c\n\x14participant_identity\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x13\n\x0bsip_call_id\x18\x04 \x01(\t\"\xa6\x02\n\x1dTransferSIPParticipantRequest\x12\x1c\n\x14participant_identity\x18\x01 \x01(\t\x12\x11\n\troom_name\x18\x02 \x01(\t\x12\x13\n\x0btransfer_to\x18\x03 \x01(\t\x12\x15\n\rplay_dialtone\x18\x04 \x01(\x08\x12\x44\n\x07headers\x18\x05 \x03(\x0b\x32\x33.livekit.TransferSIPParticipantRequest.HeadersEntry\x12\x32\n\x0fringing_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xed\x06\n\x0bSIPCallInfo\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x10\n\x08trunk_id\x18\x02 \x01(\t\x12\x18\n\x10\x64ispatch_rule_id\x18\x10 \x01(\t\x12\x0e\n\x06region\x18\x11 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x0f\n\x07room_id\x18\x04 \x01(\t\x12\x1c\n\x14participant_identity\x18\x05 \x01(\t\x12O\n\x16participant_attributes\x18\x12 \x03(\x0b\x32/.livekit.SIPCallInfo.ParticipantAttributesEntry\x12!\n\x08\x66rom_uri\x18\x06 \x01(\x0b\x32\x0f.livekit.SIPUri\x12\x1f\n\x06to_uri\x18\x07 \x01(\x0b\x32\x0f.livekit.SIPUri\x12\x16\n\ncreated_at\x18\t \x01(\x03\x42\x02\x18\x01\x12\x16\n\nstarted_at\x18\n \x01(\x03\x42\x02\x18\x01\x12\x14\n\x08\x65nded_at\x18\x0b \x01(\x03\x42\x02\x18\x01\x12-\n\x10\x65nabled_features\x18\x0e \x03(\x0e\x32\x13.livekit.SIPFeature\x12\x31\n\x0e\x63\x61ll_direction\x18\x0f \x01(\x0e\x32\x19.livekit.SIPCallDirection\x12+\n\x0b\x63\x61ll_status\x18\x08 \x01(\x0e\x32\x16.livekit.SIPCallStatus\x12\x15\n\rcreated_at_ns\x18\x16 \x01(\x03\x12\x15\n\rstarted_at_ns\x18\x17 \x01(\x03\x12\x13\n\x0b\x65nded_at_ns\x18\x18 \x01(\x03\x12\x34\n\x11\x64isconnect_reason\x18\x0c \x01(\x0e\x32\x19.livekit.DisconnectReason\x12\r\n\x05\x65rror\x18\r \x01(\t\x12,\n\x10\x63\x61ll_status_code\x18\x13 \x01(\x0b\x32\x12.livekit.SIPStatus\x12\x13\n\x0b\x61udio_codec\x18\x14 \x01(\t\x12\x18\n\x10media_encryption\x18\x15 \x01(\t\x12\x16\n\x0epcap_file_link\x18\x19 \x01(\t\x12*\n\x0c\x63\x61ll_context\x18\x1a \x03(\x0b\x32\x14.google.protobuf.Any\x1a<\n\x1aParticipantAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x86\x02\n\x0fSIPTransferInfo\x12\x13\n\x0btransfer_id\x18\x01 \x01(\t\x12\x0f\n\x07\x63\x61ll_id\x18\x02 \x01(\t\x12\x13\n\x0btransfer_to\x18\x03 \x01(\t\x12 \n\x18transfer_initiated_at_ns\x18\x04 \x01(\x03\x12 \n\x18transfer_completed_at_ns\x18\x05 \x01(\x03\x12\x33\n\x0ftransfer_status\x18\x06 \x01(\x0e\x32\x1a.livekit.SIPTransferStatus\x12\r\n\x05\x65rror\x18\x07 \x01(\t\x12\x30\n\x14transfer_status_code\x18\x08 \x01(\x0b\x32\x12.livekit.SIPStatus\"h\n\x06SIPUri\x12\x0c\n\x04user\x18\x01 \x01(\t\x12\x0c\n\x04host\x18\x02 \x01(\t\x12\n\n\x02ip\x18\x03 \x01(\t\x12\x0c\n\x04port\x18\x04 \x01(\r\x12(\n\ttransport\x18\x05 \x01(\x0e\x32\x15.livekit.SIPTransport*\xef\x0c\n\rSIPStatusCode\x12\x16\n\x12SIP_STATUS_UNKNOWN\x10\x00\x12\x15\n\x11SIP_STATUS_TRYING\x10\x64\x12\x17\n\x12SIP_STATUS_RINGING\x10\xb4\x01\x12!\n\x1cSIP_STATUS_CALL_IS_FORWARDED\x10\xb5\x01\x12\x16\n\x11SIP_STATUS_QUEUED\x10\xb6\x01\x12 \n\x1bSIP_STATUS_SESSION_PROGRESS\x10\xb7\x01\x12\x12\n\rSIP_STATUS_OK\x10\xc8\x01\x12\x18\n\x13SIP_STATUS_ACCEPTED\x10\xca\x01\x12!\n\x1cSIP_STATUS_MOVED_PERMANENTLY\x10\xad\x02\x12!\n\x1cSIP_STATUS_MOVED_TEMPORARILY\x10\xae\x02\x12\x19\n\x14SIP_STATUS_USE_PROXY\x10\xb1\x02\x12\x1b\n\x16SIP_STATUS_BAD_REQUEST\x10\x90\x03\x12\x1c\n\x17SIP_STATUS_UNAUTHORIZED\x10\x91\x03\x12 \n\x1bSIP_STATUS_PAYMENT_REQUIRED\x10\x92\x03\x12\x19\n\x14SIP_STATUS_FORBIDDEN\x10\x93\x03\x12\x18\n\x13SIP_STATUS_NOTFOUND\x10\x94\x03\x12\"\n\x1dSIP_STATUS_METHOD_NOT_ALLOWED\x10\x95\x03\x12\x1e\n\x19SIP_STATUS_NOT_ACCEPTABLE\x10\x96\x03\x12#\n\x1eSIP_STATUS_PROXY_AUTH_REQUIRED\x10\x97\x03\x12\x1f\n\x1aSIP_STATUS_REQUEST_TIMEOUT\x10\x98\x03\x12\x18\n\x13SIP_STATUS_CONFLICT\x10\x99\x03\x12\x14\n\x0fSIP_STATUS_GONE\x10\x9a\x03\x12(\n#SIP_STATUS_REQUEST_ENTITY_TOO_LARGE\x10\x9d\x03\x12$\n\x1fSIP_STATUS_REQUEST_URI_TOO_LONG\x10\x9e\x03\x12&\n!SIP_STATUS_UNSUPPORTED_MEDIA_TYPE\x10\x9f\x03\x12/\n*SIP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE\x10\xa0\x03\x12\x1d\n\x18SIP_STATUS_BAD_EXTENSION\x10\xa4\x03\x12\"\n\x1dSIP_STATUS_EXTENSION_REQUIRED\x10\xa5\x03\x12\"\n\x1dSIP_STATUS_INTERVAL_TOO_BRIEF\x10\xa7\x03\x12\'\n\"SIP_STATUS_TEMPORARILY_UNAVAILABLE\x10\xe0\x03\x12\x30\n+SIP_STATUS_CALL_TRANSACTION_DOES_NOT_EXISTS\x10\xe1\x03\x12\x1d\n\x18SIP_STATUS_LOOP_DETECTED\x10\xe2\x03\x12\x1d\n\x18SIP_STATUS_TOO_MANY_HOPS\x10\xe3\x03\x12\"\n\x1dSIP_STATUS_ADDRESS_INCOMPLETE\x10\xe4\x03\x12\x19\n\x14SIP_STATUS_AMBIGUOUS\x10\xe5\x03\x12\x19\n\x14SIP_STATUS_BUSY_HERE\x10\xe6\x03\x12\"\n\x1dSIP_STATUS_REQUEST_TERMINATED\x10\xe7\x03\x12#\n\x1eSIP_STATUS_NOT_ACCEPTABLE_HERE\x10\xe8\x03\x12%\n SIP_STATUS_INTERNAL_SERVER_ERROR\x10\xf4\x03\x12\x1f\n\x1aSIP_STATUS_NOT_IMPLEMENTED\x10\xf5\x03\x12\x1b\n\x16SIP_STATUS_BAD_GATEWAY\x10\xf6\x03\x12#\n\x1eSIP_STATUS_SERVICE_UNAVAILABLE\x10\xf7\x03\x12\x1f\n\x1aSIP_STATUS_GATEWAY_TIMEOUT\x10\xf8\x03\x12%\n SIP_STATUS_VERSION_NOT_SUPPORTED\x10\xf9\x03\x12!\n\x1cSIP_STATUS_MESSAGE_TOO_LARGE\x10\x81\x04\x12&\n!SIP_STATUS_GLOBAL_BUSY_EVERYWHERE\x10\xd8\x04\x12\x1e\n\x19SIP_STATUS_GLOBAL_DECLINE\x10\xdb\x04\x12.\n)SIP_STATUS_GLOBAL_DOES_NOT_EXIST_ANYWHERE\x10\xdc\x04\x12%\n SIP_STATUS_GLOBAL_NOT_ACCEPTABLE\x10\xde\x04*k\n\x0cSIPTransport\x12\x16\n\x12SIP_TRANSPORT_AUTO\x10\x00\x12\x15\n\x11SIP_TRANSPORT_UDP\x10\x01\x12\x15\n\x11SIP_TRANSPORT_TCP\x10\x02\x12\x15\n\x11SIP_TRANSPORT_TLS\x10\x03*N\n\x10SIPHeaderOptions\x12\x12\n\x0eSIP_NO_HEADERS\x10\x00\x12\x11\n\rSIP_X_HEADERS\x10\x01\x12\x13\n\x0fSIP_ALL_HEADERS\x10\x02*o\n\x12SIPMediaEncryption\x12\x1d\n\x19SIP_MEDIA_ENCRYPT_DISABLE\x10\x00\x12\x1b\n\x17SIP_MEDIA_ENCRYPT_ALLOW\x10\x01\x12\x1d\n\x19SIP_MEDIA_ENCRYPT_REQUIRE\x10\x02*w\n\rSIPCallStatus\x12\x15\n\x11SCS_CALL_INCOMING\x10\x00\x12\x1a\n\x16SCS_PARTICIPANT_JOINED\x10\x01\x12\x0e\n\nSCS_ACTIVE\x10\x02\x12\x14\n\x10SCS_DISCONNECTED\x10\x03\x12\r\n\tSCS_ERROR\x10\x04*c\n\x11SIPTransferStatus\x12\x18\n\x14STS_TRANSFER_ONGOING\x10\x00\x12\x17\n\x13STS_TRANSFER_FAILED\x10\x01\x12\x1b\n\x17STS_TRANSFER_SUCCESSFUL\x10\x02*)\n\nSIPFeature\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rKRISP_ENABLED\x10\x01*F\n\x10SIPCallDirection\x12\x0f\n\x0bSCD_UNKNOWN\x10\x00\x12\x0f\n\x0bSCD_INBOUND\x10\x01\x12\x10\n\x0cSCD_OUTBOUND\x10\x02\x32\xd7\x0b\n\x03SIP\x12P\n\x0cListSIPTrunk\x12\x1c.livekit.ListSIPTrunkRequest\x1a\x1d.livekit.ListSIPTrunkResponse\"\x03\x88\x02\x01\x12\\\n\x15\x43reateSIPInboundTrunk\x12%.livekit.CreateSIPInboundTrunkRequest\x1a\x1c.livekit.SIPInboundTrunkInfo\x12_\n\x16\x43reateSIPOutboundTrunk\x12&.livekit.CreateSIPOutboundTrunkRequest\x1a\x1d.livekit.SIPOutboundTrunkInfo\x12\\\n\x15UpdateSIPInboundTrunk\x12%.livekit.UpdateSIPInboundTrunkRequest\x1a\x1c.livekit.SIPInboundTrunkInfo\x12_\n\x16UpdateSIPOutboundTrunk\x12&.livekit.UpdateSIPOutboundTrunkRequest\x1a\x1d.livekit.SIPOutboundTrunkInfo\x12]\n\x12GetSIPInboundTrunk\x12\".livekit.GetSIPInboundTrunkRequest\x1a#.livekit.GetSIPInboundTrunkResponse\x12`\n\x13GetSIPOutboundTrunk\x12#.livekit.GetSIPOutboundTrunkRequest\x1a$.livekit.GetSIPOutboundTrunkResponse\x12`\n\x13ListSIPInboundTrunk\x12#.livekit.ListSIPInboundTrunkRequest\x1a$.livekit.ListSIPInboundTrunkResponse\x12\x63\n\x14ListSIPOutboundTrunk\x12$.livekit.ListSIPOutboundTrunkRequest\x1a%.livekit.ListSIPOutboundTrunkResponse\x12G\n\x0e\x44\x65leteSIPTrunk\x12\x1e.livekit.DeleteSIPTrunkRequest\x1a\x15.livekit.SIPTrunkInfo\x12\\\n\x15\x43reateSIPDispatchRule\x12%.livekit.CreateSIPDispatchRuleRequest\x1a\x1c.livekit.SIPDispatchRuleInfo\x12\\\n\x15UpdateSIPDispatchRule\x12%.livekit.UpdateSIPDispatchRuleRequest\x1a\x1c.livekit.SIPDispatchRuleInfo\x12`\n\x13ListSIPDispatchRule\x12#.livekit.ListSIPDispatchRuleRequest\x1a$.livekit.ListSIPDispatchRuleResponse\x12\\\n\x15\x44\x65leteSIPDispatchRule\x12%.livekit.DeleteSIPDispatchRuleRequest\x1a\x1c.livekit.SIPDispatchRuleInfo\x12Y\n\x14\x43reateSIPParticipant\x12$.livekit.CreateSIPParticipantRequest\x1a\x1b.livekit.SIPParticipantInfo\x12X\n\x16TransferSIPParticipant\x12&.livekit.TransferSIPParticipantRequest\x1a\x16.google.protobuf.EmptyBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" 15 | 16 | pool = Google::Protobuf::DescriptorPool.generated_pool 17 | pool.add_serialized_file(descriptor_data) 18 | 19 | module LiveKit 20 | module Proto 21 | SIPStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPStatus").msgclass 22 | CreateSIPTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPTrunkRequest").msgclass 23 | SIPTrunkInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPTrunkInfo").msgclass 24 | SIPTrunkInfo::TrunkKind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPTrunkInfo.TrunkKind").enummodule 25 | CreateSIPInboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPInboundTrunkRequest").msgclass 26 | UpdateSIPInboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateSIPInboundTrunkRequest").msgclass 27 | SIPInboundTrunkInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPInboundTrunkInfo").msgclass 28 | SIPInboundTrunkUpdate = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPInboundTrunkUpdate").msgclass 29 | CreateSIPOutboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPOutboundTrunkRequest").msgclass 30 | UpdateSIPOutboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateSIPOutboundTrunkRequest").msgclass 31 | SIPOutboundTrunkInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPOutboundTrunkInfo").msgclass 32 | SIPOutboundTrunkUpdate = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPOutboundTrunkUpdate").msgclass 33 | GetSIPInboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.GetSIPInboundTrunkRequest").msgclass 34 | GetSIPInboundTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.GetSIPInboundTrunkResponse").msgclass 35 | GetSIPOutboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.GetSIPOutboundTrunkRequest").msgclass 36 | GetSIPOutboundTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.GetSIPOutboundTrunkResponse").msgclass 37 | ListSIPTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPTrunkRequest").msgclass 38 | ListSIPTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPTrunkResponse").msgclass 39 | ListSIPInboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPInboundTrunkRequest").msgclass 40 | ListSIPInboundTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPInboundTrunkResponse").msgclass 41 | ListSIPOutboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPOutboundTrunkRequest").msgclass 42 | ListSIPOutboundTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPOutboundTrunkResponse").msgclass 43 | DeleteSIPTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DeleteSIPTrunkRequest").msgclass 44 | SIPDispatchRuleDirect = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRuleDirect").msgclass 45 | SIPDispatchRuleIndividual = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRuleIndividual").msgclass 46 | SIPDispatchRuleCallee = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRuleCallee").msgclass 47 | SIPDispatchRule = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRule").msgclass 48 | CreateSIPDispatchRuleRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPDispatchRuleRequest").msgclass 49 | UpdateSIPDispatchRuleRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateSIPDispatchRuleRequest").msgclass 50 | SIPDispatchRuleInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRuleInfo").msgclass 51 | SIPDispatchRuleUpdate = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRuleUpdate").msgclass 52 | ListSIPDispatchRuleRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPDispatchRuleRequest").msgclass 53 | ListSIPDispatchRuleResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPDispatchRuleResponse").msgclass 54 | DeleteSIPDispatchRuleRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DeleteSIPDispatchRuleRequest").msgclass 55 | SIPOutboundConfig = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPOutboundConfig").msgclass 56 | CreateSIPParticipantRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPParticipantRequest").msgclass 57 | SIPParticipantInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPParticipantInfo").msgclass 58 | TransferSIPParticipantRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TransferSIPParticipantRequest").msgclass 59 | SIPCallInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPCallInfo").msgclass 60 | SIPTransferInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPTransferInfo").msgclass 61 | SIPUri = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPUri").msgclass 62 | SIPStatusCode = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPStatusCode").enummodule 63 | SIPTransport = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPTransport").enummodule 64 | SIPHeaderOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPHeaderOptions").enummodule 65 | SIPMediaEncryption = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPMediaEncryption").enummodule 66 | SIPCallStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPCallStatus").enummodule 67 | SIPTransferStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPTransferStatus").enummodule 68 | SIPFeature = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPFeature").enummodule 69 | SIPCallDirection = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPCallDirection").enummodule 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /lib/livekit/proto/livekit_models_pb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: livekit_models.proto 4 | 5 | require 'google/protobuf' 6 | 7 | require 'google/protobuf/timestamp_pb' 8 | require 'livekit_metrics_pb' 9 | 10 | 11 | descriptor_data = "\n\x14livekit_models.proto\x12\x07livekit\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x15livekit_metrics.proto\"-\n\nPagination\x12\x10\n\x08\x61\x66ter_id\x18\x01 \x01(\t\x12\r\n\x05limit\x18\x02 \x01(\x05\" \n\x0fTokenPagination\x12\r\n\x05token\x18\x01 \x01(\t\"E\n\nListUpdate\x12\x0b\n\x03set\x18\x01 \x03(\t\x12\x0b\n\x03\x61\x64\x64\x18\x02 \x03(\t\x12\x0e\n\x06remove\x18\x03 \x03(\t\x12\r\n\x05\x63lear\x18\x04 \x01(\x08\"\xe3\x02\n\x04Room\x12\x0b\n\x03sid\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x15\n\rempty_timeout\x18\x03 \x01(\r\x12\x19\n\x11\x64\x65parture_timeout\x18\x0e \x01(\r\x12\x18\n\x10max_participants\x18\x04 \x01(\r\x12\x15\n\rcreation_time\x18\x05 \x01(\x03\x12\x18\n\x10\x63reation_time_ms\x18\x0f \x01(\x03\x12\x15\n\rturn_password\x18\x06 \x01(\t\x12&\n\x0e\x65nabled_codecs\x18\x07 \x03(\x0b\x32\x0e.livekit.Codec\x12\x10\n\x08metadata\x18\x08 \x01(\t\x12\x18\n\x10num_participants\x18\t \x01(\r\x12\x16\n\x0enum_publishers\x18\x0b \x01(\r\x12\x18\n\x10\x61\x63tive_recording\x18\n \x01(\x08\x12&\n\x07version\x18\r \x01(\x0b\x32\x15.livekit.TimedVersion\"(\n\x05\x43odec\x12\x0c\n\x04mime\x18\x01 \x01(\t\x12\x11\n\tfmtp_line\x18\x02 \x01(\t\"9\n\x0cPlayoutDelay\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0b\n\x03min\x18\x02 \x01(\r\x12\x0b\n\x03max\x18\x03 \x01(\r\"\x85\x02\n\x15ParticipantPermission\x12\x15\n\rcan_subscribe\x18\x01 \x01(\x08\x12\x13\n\x0b\x63\x61n_publish\x18\x02 \x01(\x08\x12\x18\n\x10\x63\x61n_publish_data\x18\x03 \x01(\x08\x12\x31\n\x13\x63\x61n_publish_sources\x18\t \x03(\x0e\x32\x14.livekit.TrackSource\x12\x0e\n\x06hidden\x18\x07 \x01(\x08\x12\x14\n\x08recorder\x18\x08 \x01(\x08\x42\x02\x18\x01\x12\x1b\n\x13\x63\x61n_update_metadata\x18\n \x01(\x08\x12\x11\n\x05\x61gent\x18\x0b \x01(\x08\x42\x02\x18\x01\x12\x1d\n\x15\x63\x61n_subscribe_metrics\x18\x0c \x01(\x08\"\xf7\x05\n\x0fParticipantInfo\x12\x0b\n\x03sid\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12-\n\x05state\x18\x03 \x01(\x0e\x32\x1e.livekit.ParticipantInfo.State\x12\"\n\x06tracks\x18\x04 \x03(\x0b\x32\x12.livekit.TrackInfo\x12\x10\n\x08metadata\x18\x05 \x01(\t\x12\x11\n\tjoined_at\x18\x06 \x01(\x03\x12\x14\n\x0cjoined_at_ms\x18\x11 \x01(\x03\x12\x0c\n\x04name\x18\t \x01(\t\x12\x0f\n\x07version\x18\n \x01(\r\x12\x32\n\npermission\x18\x0b \x01(\x0b\x32\x1e.livekit.ParticipantPermission\x12\x0e\n\x06region\x18\x0c \x01(\t\x12\x14\n\x0cis_publisher\x18\r \x01(\x08\x12+\n\x04kind\x18\x0e \x01(\x0e\x32\x1d.livekit.ParticipantInfo.Kind\x12<\n\nattributes\x18\x0f \x03(\x0b\x32(.livekit.ParticipantInfo.AttributesEntry\x12\x34\n\x11\x64isconnect_reason\x18\x10 \x01(\x0e\x32\x19.livekit.DisconnectReason\x12\x39\n\x0ckind_details\x18\x12 \x03(\x0e\x32#.livekit.ParticipantInfo.KindDetail\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\">\n\x05State\x12\x0b\n\x07JOINING\x10\x00\x12\n\n\x06JOINED\x10\x01\x12\n\n\x06\x41\x43TIVE\x10\x02\x12\x10\n\x0c\x44ISCONNECTED\x10\x03\"A\n\x04Kind\x12\x0c\n\x08STANDARD\x10\x00\x12\x0b\n\x07INGRESS\x10\x01\x12\n\n\x06\x45GRESS\x10\x02\x12\x07\n\x03SIP\x10\x03\x12\t\n\x05\x41GENT\x10\x04\",\n\nKindDetail\x12\x0f\n\x0b\x43LOUD_AGENT\x10\x00\x12\r\n\tFORWARDED\x10\x01\"3\n\nEncryption\"%\n\x04Type\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03GCM\x10\x01\x12\n\n\x06\x43USTOM\x10\x02\"\xab\x01\n\x12SimulcastCodecInfo\x12\x11\n\tmime_type\x18\x01 \x01(\t\x12\x0b\n\x03mid\x18\x02 \x01(\t\x12\x0b\n\x03\x63id\x18\x03 \x01(\t\x12#\n\x06layers\x18\x04 \x03(\x0b\x32\x13.livekit.VideoLayer\x12\x32\n\x10video_layer_mode\x18\x05 \x01(\x0e\x32\x18.livekit.VideoLayer.Mode\x12\x0f\n\x07sdp_cid\x18\x06 \x01(\t\"\xbe\x04\n\tTrackInfo\x12\x0b\n\x03sid\x18\x01 \x01(\t\x12 \n\x04type\x18\x02 \x01(\x0e\x32\x12.livekit.TrackType\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\r\n\x05muted\x18\x04 \x01(\x08\x12\r\n\x05width\x18\x05 \x01(\r\x12\x0e\n\x06height\x18\x06 \x01(\r\x12\x15\n\tsimulcast\x18\x07 \x01(\x08\x42\x02\x18\x01\x12\x17\n\x0b\x64isable_dtx\x18\x08 \x01(\x08\x42\x02\x18\x01\x12$\n\x06source\x18\t \x01(\x0e\x32\x14.livekit.TrackSource\x12\'\n\x06layers\x18\n \x03(\x0b\x32\x13.livekit.VideoLayerB\x02\x18\x01\x12\x11\n\tmime_type\x18\x0b \x01(\t\x12\x0b\n\x03mid\x18\x0c \x01(\t\x12+\n\x06\x63odecs\x18\r \x03(\x0b\x32\x1b.livekit.SimulcastCodecInfo\x12\x12\n\x06stereo\x18\x0e \x01(\x08\x42\x02\x18\x01\x12\x13\n\x0b\x64isable_red\x18\x0f \x01(\x08\x12,\n\nencryption\x18\x10 \x01(\x0e\x32\x18.livekit.Encryption.Type\x12\x0e\n\x06stream\x18\x11 \x01(\t\x12&\n\x07version\x18\x12 \x01(\x0b\x32\x15.livekit.TimedVersion\x12\x32\n\x0e\x61udio_features\x18\x13 \x03(\x0e\x32\x1a.livekit.AudioTrackFeature\x12\x37\n\x13\x62\x61\x63kup_codec_policy\x18\x14 \x01(\x0e\x32\x1a.livekit.BackupCodecPolicy\"\xaf\x02\n\nVideoLayer\x12&\n\x07quality\x18\x01 \x01(\x0e\x32\x15.livekit.VideoQuality\x12\r\n\x05width\x18\x02 \x01(\r\x12\x0e\n\x06height\x18\x03 \x01(\r\x12\x0f\n\x07\x62itrate\x18\x04 \x01(\r\x12\x0c\n\x04ssrc\x18\x05 \x01(\r\x12\x15\n\rspatial_layer\x18\x06 \x01(\x05\x12\x0b\n\x03rid\x18\x07 \x01(\t\"\x96\x01\n\x04Mode\x12\x0f\n\x0bMODE_UNUSED\x10\x00\x12 \n\x1cONE_SPATIAL_LAYER_PER_STREAM\x10\x01\x12&\n\"MULTIPLE_SPATIAL_LAYERS_PER_STREAM\x10\x02\x12\x33\n/ONE_SPATIAL_LAYER_PER_STREAM_INCOMPLETE_RTCP_SR\x10\x03\"\xa7\x06\n\nDataPacket\x12*\n\x04kind\x18\x01 \x01(\x0e\x32\x18.livekit.DataPacket.KindB\x02\x18\x01\x12\x1c\n\x14participant_identity\x18\x04 \x01(\t\x12\x1e\n\x16\x64\x65stination_identities\x18\x05 \x03(\t\x12#\n\x04user\x18\x02 \x01(\x0b\x32\x13.livekit.UserPacketH\x00\x12\x33\n\x07speaker\x18\x03 \x01(\x0b\x32\x1c.livekit.ActiveSpeakerUpdateB\x02\x18\x01H\x00\x12$\n\x08sip_dtmf\x18\x06 \x01(\x0b\x32\x10.livekit.SipDTMFH\x00\x12/\n\rtranscription\x18\x07 \x01(\x0b\x32\x16.livekit.TranscriptionH\x00\x12(\n\x07metrics\x18\x08 \x01(\x0b\x32\x15.livekit.MetricsBatchH\x00\x12,\n\x0c\x63hat_message\x18\t \x01(\x0b\x32\x14.livekit.ChatMessageH\x00\x12*\n\x0brpc_request\x18\n \x01(\x0b\x32\x13.livekit.RpcRequestH\x00\x12\"\n\x07rpc_ack\x18\x0b \x01(\x0b\x32\x0f.livekit.RpcAckH\x00\x12,\n\x0crpc_response\x18\x0c \x01(\x0b\x32\x14.livekit.RpcResponseH\x00\x12\x33\n\rstream_header\x18\r \x01(\x0b\x32\x1a.livekit.DataStream.HeaderH\x00\x12\x31\n\x0cstream_chunk\x18\x0e \x01(\x0b\x32\x19.livekit.DataStream.ChunkH\x00\x12\x35\n\x0estream_trailer\x18\x0f \x01(\x0b\x32\x1b.livekit.DataStream.TrailerH\x00\x12\x34\n\x10\x65ncrypted_packet\x18\x12 \x01(\x0b\x32\x18.livekit.EncryptedPacketH\x00\x12\x10\n\x08sequence\x18\x10 \x01(\r\x12\x17\n\x0fparticipant_sid\x18\x11 \x01(\t\"\x1f\n\x04Kind\x12\x0c\n\x08RELIABLE\x10\x00\x12\t\n\x05LOSSY\x10\x01\x42\x07\n\x05value\"|\n\x0f\x45ncryptedPacket\x12\x31\n\x0f\x65ncryption_type\x18\x01 \x01(\x0e\x32\x18.livekit.Encryption.Type\x12\n\n\x02iv\x18\x02 \x01(\x0c\x12\x11\n\tkey_index\x18\x03 \x01(\r\x12\x17\n\x0f\x65ncrypted_value\x18\x04 \x01(\x0c\"\x91\x03\n\x16\x45ncryptedPacketPayload\x12#\n\x04user\x18\x01 \x01(\x0b\x32\x13.livekit.UserPacketH\x00\x12,\n\x0c\x63hat_message\x18\x03 \x01(\x0b\x32\x14.livekit.ChatMessageH\x00\x12*\n\x0brpc_request\x18\x04 \x01(\x0b\x32\x13.livekit.RpcRequestH\x00\x12\"\n\x07rpc_ack\x18\x05 \x01(\x0b\x32\x0f.livekit.RpcAckH\x00\x12,\n\x0crpc_response\x18\x06 \x01(\x0b\x32\x14.livekit.RpcResponseH\x00\x12\x33\n\rstream_header\x18\x07 \x01(\x0b\x32\x1a.livekit.DataStream.HeaderH\x00\x12\x31\n\x0cstream_chunk\x18\x08 \x01(\x0b\x32\x19.livekit.DataStream.ChunkH\x00\x12\x35\n\x0estream_trailer\x18\t \x01(\x0b\x32\x1b.livekit.DataStream.TrailerH\x00\x42\x07\n\x05value\"A\n\x13\x41\x63tiveSpeakerUpdate\x12&\n\x08speakers\x18\x01 \x03(\x0b\x32\x14.livekit.SpeakerInfo:\x02\x18\x01\"9\n\x0bSpeakerInfo\x12\x0b\n\x03sid\x18\x01 \x01(\t\x12\r\n\x05level\x18\x02 \x01(\x02\x12\x0e\n\x06\x61\x63tive\x18\x03 \x01(\x08\"\xaf\x02\n\nUserPacket\x12\x1b\n\x0fparticipant_sid\x18\x01 \x01(\tB\x02\x18\x01\x12 \n\x14participant_identity\x18\x05 \x01(\tB\x02\x18\x01\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\x12\x1c\n\x10\x64\x65stination_sids\x18\x03 \x03(\tB\x02\x18\x01\x12\"\n\x16\x64\x65stination_identities\x18\x06 \x03(\tB\x02\x18\x01\x12\x12\n\x05topic\x18\x04 \x01(\tH\x00\x88\x01\x01\x12\x0f\n\x02id\x18\x08 \x01(\tH\x01\x88\x01\x01\x12\x17\n\nstart_time\x18\t \x01(\x04H\x02\x88\x01\x01\x12\x15\n\x08\x65nd_time\x18\n \x01(\x04H\x03\x88\x01\x01\x12\r\n\x05nonce\x18\x0b \x01(\x0c\x42\x08\n\x06_topicB\x05\n\x03_idB\r\n\x0b_start_timeB\x0b\n\t_end_time\"&\n\x07SipDTMF\x12\x0c\n\x04\x63ode\x18\x03 \x01(\r\x12\r\n\x05\x64igit\x18\x04 \x01(\t\"|\n\rTranscription\x12(\n transcribed_participant_identity\x18\x02 \x01(\t\x12\x10\n\x08track_id\x18\x03 \x01(\t\x12/\n\x08segments\x18\x04 \x03(\x0b\x32\x1d.livekit.TranscriptionSegment\"w\n\x14TranscriptionSegment\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x12\n\nstart_time\x18\x03 \x01(\x04\x12\x10\n\x08\x65nd_time\x18\x04 \x01(\x04\x12\r\n\x05\x66inal\x18\x05 \x01(\x08\x12\x10\n\x08language\x18\x06 \x01(\t\"\x91\x01\n\x0b\x43hatMessage\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\x03\x12\x1b\n\x0e\x65\x64it_timestamp\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12\x0f\n\x07message\x18\x04 \x01(\t\x12\x0f\n\x07\x64\x65leted\x18\x05 \x01(\x08\x12\x11\n\tgenerated\x18\x06 \x01(\x08\x42\x11\n\x0f_edit_timestamp\"g\n\nRpcRequest\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0e\n\x06method\x18\x02 \x01(\t\x12\x0f\n\x07payload\x18\x03 \x01(\t\x12\x1b\n\x13response_timeout_ms\x18\x04 \x01(\r\x12\x0f\n\x07version\x18\x05 \x01(\r\"\x1c\n\x06RpcAck\x12\x12\n\nrequest_id\x18\x01 \x01(\t\"a\n\x0bRpcResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x11\n\x07payload\x18\x02 \x01(\tH\x00\x12\"\n\x05\x65rror\x18\x03 \x01(\x0b\x32\x11.livekit.RpcErrorH\x00\x42\x07\n\x05value\"7\n\x08RpcError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\t\"@\n\x11ParticipantTracks\x12\x17\n\x0fparticipant_sid\x18\x01 \x01(\t\x12\x12\n\ntrack_sids\x18\x02 \x03(\t\"\xce\x01\n\nServerInfo\x12,\n\x07\x65\x64ition\x18\x01 \x01(\x0e\x32\x1b.livekit.ServerInfo.Edition\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x10\n\x08protocol\x18\x03 \x01(\x05\x12\x0e\n\x06region\x18\x04 \x01(\t\x12\x0f\n\x07node_id\x18\x05 \x01(\t\x12\x12\n\ndebug_info\x18\x06 \x01(\t\x12\x16\n\x0e\x61gent_protocol\x18\x07 \x01(\x05\"\"\n\x07\x45\x64ition\x12\x0c\n\x08Standard\x10\x00\x12\t\n\x05\x43loud\x10\x01\"\xa1\x03\n\nClientInfo\x12$\n\x03sdk\x18\x01 \x01(\x0e\x32\x17.livekit.ClientInfo.SDK\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x10\n\x08protocol\x18\x03 \x01(\x05\x12\n\n\x02os\x18\x04 \x01(\t\x12\x12\n\nos_version\x18\x05 \x01(\t\x12\x14\n\x0c\x64\x65vice_model\x18\x06 \x01(\t\x12\x0f\n\x07\x62rowser\x18\x07 \x01(\t\x12\x17\n\x0f\x62rowser_version\x18\x08 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\t \x01(\t\x12\x0f\n\x07network\x18\n \x01(\t\x12\x12\n\nother_sdks\x18\x0b \x01(\t\"\xb3\x01\n\x03SDK\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x06\n\x02JS\x10\x01\x12\t\n\x05SWIFT\x10\x02\x12\x0b\n\x07\x41NDROID\x10\x03\x12\x0b\n\x07\x46LUTTER\x10\x04\x12\x06\n\x02GO\x10\x05\x12\t\n\x05UNITY\x10\x06\x12\x10\n\x0cREACT_NATIVE\x10\x07\x12\x08\n\x04RUST\x10\x08\x12\n\n\x06PYTHON\x10\t\x12\x07\n\x03\x43PP\x10\n\x12\r\n\tUNITY_WEB\x10\x0b\x12\x08\n\x04NODE\x10\x0c\x12\n\n\x06UNREAL\x10\r\x12\t\n\x05\x45SP32\x10\x0e\"\x8c\x02\n\x13\x43lientConfiguration\x12*\n\x05video\x18\x01 \x01(\x0b\x32\x1b.livekit.VideoConfiguration\x12+\n\x06screen\x18\x02 \x01(\x0b\x32\x1b.livekit.VideoConfiguration\x12\x37\n\x11resume_connection\x18\x03 \x01(\x0e\x32\x1c.livekit.ClientConfigSetting\x12\x30\n\x0f\x64isabled_codecs\x18\x04 \x01(\x0b\x32\x17.livekit.DisabledCodecs\x12\x31\n\x0b\x66orce_relay\x18\x05 \x01(\x0e\x32\x1c.livekit.ClientConfigSetting\"L\n\x12VideoConfiguration\x12\x36\n\x10hardware_encoder\x18\x01 \x01(\x0e\x32\x1c.livekit.ClientConfigSetting\"Q\n\x0e\x44isabledCodecs\x12\x1e\n\x06\x63odecs\x18\x01 \x03(\x0b\x32\x0e.livekit.Codec\x12\x1f\n\x07publish\x18\x02 \x03(\x0b\x32\x0e.livekit.Codec\"\x80\x02\n\x08RTPDrift\x12.\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x64uration\x18\x03 \x01(\x01\x12\x17\n\x0fstart_timestamp\x18\x04 \x01(\x04\x12\x15\n\rend_timestamp\x18\x05 \x01(\x04\x12\x17\n\x0frtp_clock_ticks\x18\x06 \x01(\x04\x12\x15\n\rdrift_samples\x18\x07 \x01(\x03\x12\x10\n\x08\x64rift_ms\x18\x08 \x01(\x01\x12\x12\n\nclock_rate\x18\t \x01(\x01\"\xd6\n\n\x08RTPStats\x12.\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x64uration\x18\x03 \x01(\x01\x12\x0f\n\x07packets\x18\x04 \x01(\r\x12\x13\n\x0bpacket_rate\x18\x05 \x01(\x01\x12\r\n\x05\x62ytes\x18\x06 \x01(\x04\x12\x14\n\x0cheader_bytes\x18\' \x01(\x04\x12\x0f\n\x07\x62itrate\x18\x07 \x01(\x01\x12\x14\n\x0cpackets_lost\x18\x08 \x01(\r\x12\x18\n\x10packet_loss_rate\x18\t \x01(\x01\x12\x1e\n\x16packet_loss_percentage\x18\n \x01(\x02\x12\x19\n\x11packets_duplicate\x18\x0b \x01(\r\x12\x1d\n\x15packet_duplicate_rate\x18\x0c \x01(\x01\x12\x17\n\x0f\x62ytes_duplicate\x18\r \x01(\x04\x12\x1e\n\x16header_bytes_duplicate\x18( \x01(\x04\x12\x19\n\x11\x62itrate_duplicate\x18\x0e \x01(\x01\x12\x17\n\x0fpackets_padding\x18\x0f \x01(\r\x12\x1b\n\x13packet_padding_rate\x18\x10 \x01(\x01\x12\x15\n\rbytes_padding\x18\x11 \x01(\x04\x12\x1c\n\x14header_bytes_padding\x18) \x01(\x04\x12\x17\n\x0f\x62itrate_padding\x18\x12 \x01(\x01\x12\x1c\n\x14packets_out_of_order\x18\x13 \x01(\r\x12\x0e\n\x06\x66rames\x18\x14 \x01(\r\x12\x12\n\nframe_rate\x18\x15 \x01(\x01\x12\x16\n\x0ejitter_current\x18\x16 \x01(\x01\x12\x12\n\njitter_max\x18\x17 \x01(\x01\x12:\n\rgap_histogram\x18\x18 \x03(\x0b\x32#.livekit.RTPStats.GapHistogramEntry\x12\r\n\x05nacks\x18\x19 \x01(\r\x12\x11\n\tnack_acks\x18% \x01(\r\x12\x13\n\x0bnack_misses\x18\x1a \x01(\r\x12\x15\n\rnack_repeated\x18& \x01(\r\x12\x0c\n\x04plis\x18\x1b \x01(\r\x12,\n\x08last_pli\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0c\n\x04\x66irs\x18\x1d \x01(\r\x12,\n\x08last_fir\x18\x1e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x13\n\x0brtt_current\x18\x1f \x01(\r\x12\x0f\n\x07rtt_max\x18 \x01(\r\x12\x12\n\nkey_frames\x18! \x01(\r\x12\x32\n\x0elast_key_frame\x18\" \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0flayer_lock_plis\x18# \x01(\r\x12\x37\n\x13last_layer_lock_pli\x18$ \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\'\n\x0cpacket_drift\x18, \x01(\x0b\x32\x11.livekit.RTPDrift\x12+\n\x10ntp_report_drift\x18- \x01(\x0b\x32\x11.livekit.RTPDrift\x12/\n\x14rebased_report_drift\x18. \x01(\x0b\x32\x11.livekit.RTPDrift\x12\x30\n\x15received_report_drift\x18/ \x01(\x0b\x32\x11.livekit.RTPDrift\x1a\x33\n\x11GapHistogramEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xa2\x01\n\x15RTCPSenderReportState\x12\x15\n\rrtp_timestamp\x18\x01 \x01(\r\x12\x19\n\x11rtp_timestamp_ext\x18\x02 \x01(\x04\x12\x15\n\rntp_timestamp\x18\x03 \x01(\x04\x12\n\n\x02\x61t\x18\x04 \x01(\x03\x12\x13\n\x0b\x61t_adjusted\x18\x05 \x01(\x03\x12\x0f\n\x07packets\x18\x06 \x01(\r\x12\x0e\n\x06octets\x18\x07 \x01(\x04\"\xc9\x02\n\x11RTPForwarderState\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x1f\n\x17reference_layer_spatial\x18\x02 \x01(\x05\x12\x16\n\x0epre_start_time\x18\x03 \x01(\x03\x12\x1b\n\x13\x65xt_first_timestamp\x18\x04 \x01(\x04\x12$\n\x1c\x64ummy_start_timestamp_offset\x18\x05 \x01(\x04\x12+\n\nrtp_munger\x18\x06 \x01(\x0b\x32\x17.livekit.RTPMungerState\x12-\n\nvp8_munger\x18\x07 \x01(\x0b\x32\x17.livekit.VP8MungerStateH\x00\x12;\n\x13sender_report_state\x18\x08 \x03(\x0b\x32\x1e.livekit.RTCPSenderReportStateB\x0e\n\x0c\x63odec_munger\"\xcb\x01\n\x0eRTPMungerState\x12 \n\x18\x65xt_last_sequence_number\x18\x01 \x01(\x04\x12\'\n\x1f\x65xt_second_last_sequence_number\x18\x02 \x01(\x04\x12\x1a\n\x12\x65xt_last_timestamp\x18\x03 \x01(\x04\x12!\n\x19\x65xt_second_last_timestamp\x18\x04 \x01(\x04\x12\x13\n\x0blast_marker\x18\x05 \x01(\x08\x12\x1a\n\x12second_last_marker\x18\x06 \x01(\x08\"\xb8\x01\n\x0eVP8MungerState\x12\x1b\n\x13\x65xt_last_picture_id\x18\x01 \x01(\x05\x12\x17\n\x0fpicture_id_used\x18\x02 \x01(\x08\x12\x18\n\x10last_tl0_pic_idx\x18\x03 \x01(\r\x12\x18\n\x10tl0_pic_idx_used\x18\x04 \x01(\x08\x12\x10\n\x08tid_used\x18\x05 \x01(\x08\x12\x14\n\x0clast_key_idx\x18\x06 \x01(\r\x12\x14\n\x0ckey_idx_used\x18\x07 \x01(\x08\"1\n\x0cTimedVersion\x12\x12\n\nunix_micro\x18\x01 \x01(\x03\x12\r\n\x05ticks\x18\x02 \x01(\x05\"\xcd\x07\n\nDataStream\x1a\xa4\x01\n\nTextHeader\x12\x39\n\x0eoperation_type\x18\x01 \x01(\x0e\x32!.livekit.DataStream.OperationType\x12\x0f\n\x07version\x18\x02 \x01(\x05\x12\x1a\n\x12reply_to_stream_id\x18\x03 \x01(\t\x12\x1b\n\x13\x61ttached_stream_ids\x18\x04 \x03(\t\x12\x11\n\tgenerated\x18\x05 \x01(\x08\x1a\x1a\n\nByteHeader\x12\x0c\n\x04name\x18\x01 \x01(\t\x1a\xa6\x03\n\x06Header\x12\x11\n\tstream_id\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\x03\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\x12\x19\n\x0ctotal_length\x18\x05 \x01(\x04H\x01\x88\x01\x01\x12\x35\n\x0f\x65ncryption_type\x18\x07 \x01(\x0e\x32\x18.livekit.Encryption.TypeB\x02\x18\x01\x12>\n\nattributes\x18\x08 \x03(\x0b\x32*.livekit.DataStream.Header.AttributesEntry\x12\x35\n\x0btext_header\x18\t \x01(\x0b\x32\x1e.livekit.DataStream.TextHeaderH\x00\x12\x35\n\x0b\x62yte_header\x18\n \x01(\x0b\x32\x1e.livekit.DataStream.ByteHeaderH\x00\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x10\n\x0e\x63ontent_headerB\x0f\n\r_total_length\x1am\n\x05\x43hunk\x12\x11\n\tstream_id\x18\x01 \x01(\t\x12\x13\n\x0b\x63hunk_index\x18\x02 \x01(\x04\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\x05\x12\x13\n\x02iv\x18\x05 \x01(\x0c\x42\x02\x18\x01H\x00\x88\x01\x01\x42\x05\n\x03_iv\x1a\xa0\x01\n\x07Trailer\x12\x11\n\tstream_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12?\n\nattributes\x18\x03 \x03(\x0b\x32+.livekit.DataStream.Trailer.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"A\n\rOperationType\x12\n\n\x06\x43REATE\x10\x00\x12\n\n\x06UPDATE\x10\x01\x12\n\n\x06\x44\x45LETE\x10\x02\x12\x0c\n\x08REACTION\x10\x03\"1\n\rWebhookConfig\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x13\n\x0bsigning_key\x18\x02 \x01(\t\"6\n\x14SubscribedAudioCodec\x12\r\n\x05\x63odec\x18\x01 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x02 \x01(\x08*;\n\nAudioCodec\x12\x0e\n\nDEFAULT_AC\x10\x00\x12\x08\n\x04OPUS\x10\x01\x12\x07\n\x03\x41\x41\x43\x10\x02\x12\n\n\x06\x41\x43_MP3\x10\x03*V\n\nVideoCodec\x12\x0e\n\nDEFAULT_VC\x10\x00\x12\x11\n\rH264_BASELINE\x10\x01\x12\r\n\tH264_MAIN\x10\x02\x12\r\n\tH264_HIGH\x10\x03\x12\x07\n\x03VP8\x10\x04*)\n\nImageCodec\x12\x0e\n\nIC_DEFAULT\x10\x00\x12\x0b\n\x07IC_JPEG\x10\x01*I\n\x11\x42\x61\x63kupCodecPolicy\x12\x15\n\x11PREFER_REGRESSION\x10\x00\x12\r\n\tSIMULCAST\x10\x01\x12\x0e\n\nREGRESSION\x10\x02*+\n\tTrackType\x12\t\n\x05\x41UDIO\x10\x00\x12\t\n\x05VIDEO\x10\x01\x12\x08\n\x04\x44\x41TA\x10\x02*`\n\x0bTrackSource\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06\x43\x41MERA\x10\x01\x12\x0e\n\nMICROPHONE\x10\x02\x12\x10\n\x0cSCREEN_SHARE\x10\x03\x12\x16\n\x12SCREEN_SHARE_AUDIO\x10\x04*6\n\x0cVideoQuality\x12\x07\n\x03LOW\x10\x00\x12\n\n\x06MEDIUM\x10\x01\x12\x08\n\x04HIGH\x10\x02\x12\x07\n\x03OFF\x10\x03*@\n\x11\x43onnectionQuality\x12\x08\n\x04POOR\x10\x00\x12\x08\n\x04GOOD\x10\x01\x12\r\n\tEXCELLENT\x10\x02\x12\x08\n\x04LOST\x10\x03*;\n\x13\x43lientConfigSetting\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x44ISABLED\x10\x01\x12\x0b\n\x07\x45NABLED\x10\x02*\xd7\x02\n\x10\x44isconnectReason\x12\x12\n\x0eUNKNOWN_REASON\x10\x00\x12\x14\n\x10\x43LIENT_INITIATED\x10\x01\x12\x16\n\x12\x44UPLICATE_IDENTITY\x10\x02\x12\x13\n\x0fSERVER_SHUTDOWN\x10\x03\x12\x17\n\x13PARTICIPANT_REMOVED\x10\x04\x12\x10\n\x0cROOM_DELETED\x10\x05\x12\x12\n\x0eSTATE_MISMATCH\x10\x06\x12\x10\n\x0cJOIN_FAILURE\x10\x07\x12\r\n\tMIGRATION\x10\x08\x12\x10\n\x0cSIGNAL_CLOSE\x10\t\x12\x0f\n\x0bROOM_CLOSED\x10\n\x12\x14\n\x10USER_UNAVAILABLE\x10\x0b\x12\x11\n\rUSER_REJECTED\x10\x0c\x12\x15\n\x11SIP_TRUNK_FAILURE\x10\r\x12\x16\n\x12\x43ONNECTION_TIMEOUT\x10\x0e\x12\x11\n\rMEDIA_FAILURE\x10\x0f*\x89\x01\n\x0fReconnectReason\x12\x0e\n\nRR_UNKNOWN\x10\x00\x12\x1a\n\x16RR_SIGNAL_DISCONNECTED\x10\x01\x12\x17\n\x13RR_PUBLISHER_FAILED\x10\x02\x12\x18\n\x14RR_SUBSCRIBER_FAILED\x10\x03\x12\x17\n\x13RR_SWITCH_CANDIDATE\x10\x04*T\n\x11SubscriptionError\x12\x0e\n\nSE_UNKNOWN\x10\x00\x12\x18\n\x14SE_CODEC_UNSUPPORTED\x10\x01\x12\x15\n\x11SE_TRACK_NOTFOUND\x10\x02*\xbd\x01\n\x11\x41udioTrackFeature\x12\r\n\tTF_STEREO\x10\x00\x12\r\n\tTF_NO_DTX\x10\x01\x12\x18\n\x14TF_AUTO_GAIN_CONTROL\x10\x02\x12\x18\n\x14TF_ECHO_CANCELLATION\x10\x03\x12\x18\n\x14TF_NOISE_SUPPRESSION\x10\x04\x12\"\n\x1eTF_ENHANCED_NOISE_CANCELLATION\x10\x05\x12\x18\n\x14TF_PRECONNECT_BUFFER\x10\x06\x42\x46Z#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" 12 | 13 | pool = Google::Protobuf::DescriptorPool.generated_pool 14 | pool.add_serialized_file(descriptor_data) 15 | 16 | module LiveKit 17 | module Proto 18 | Pagination = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Pagination").msgclass 19 | TokenPagination = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TokenPagination").msgclass 20 | ListUpdate = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListUpdate").msgclass 21 | Room = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Room").msgclass 22 | Codec = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Codec").msgclass 23 | PlayoutDelay = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.PlayoutDelay").msgclass 24 | ParticipantPermission = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantPermission").msgclass 25 | ParticipantInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantInfo").msgclass 26 | ParticipantInfo::State = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantInfo.State").enummodule 27 | ParticipantInfo::Kind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantInfo.Kind").enummodule 28 | ParticipantInfo::KindDetail = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantInfo.KindDetail").enummodule 29 | Encryption = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Encryption").msgclass 30 | Encryption::Type = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Encryption.Type").enummodule 31 | SimulcastCodecInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SimulcastCodecInfo").msgclass 32 | TrackInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TrackInfo").msgclass 33 | VideoLayer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VideoLayer").msgclass 34 | VideoLayer::Mode = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VideoLayer.Mode").enummodule 35 | DataPacket = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataPacket").msgclass 36 | DataPacket::Kind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataPacket.Kind").enummodule 37 | EncryptedPacket = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EncryptedPacket").msgclass 38 | EncryptedPacketPayload = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EncryptedPacketPayload").msgclass 39 | ActiveSpeakerUpdate = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ActiveSpeakerUpdate").msgclass 40 | SpeakerInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SpeakerInfo").msgclass 41 | UserPacket = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UserPacket").msgclass 42 | SipDTMF = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SipDTMF").msgclass 43 | Transcription = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Transcription").msgclass 44 | TranscriptionSegment = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TranscriptionSegment").msgclass 45 | ChatMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ChatMessage").msgclass 46 | RpcRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RpcRequest").msgclass 47 | RpcAck = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RpcAck").msgclass 48 | RpcResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RpcResponse").msgclass 49 | RpcError = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RpcError").msgclass 50 | ParticipantTracks = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantTracks").msgclass 51 | ServerInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ServerInfo").msgclass 52 | ServerInfo::Edition = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ServerInfo.Edition").enummodule 53 | ClientInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ClientInfo").msgclass 54 | ClientInfo::SDK = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ClientInfo.SDK").enummodule 55 | ClientConfiguration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ClientConfiguration").msgclass 56 | VideoConfiguration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VideoConfiguration").msgclass 57 | DisabledCodecs = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DisabledCodecs").msgclass 58 | RTPDrift = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTPDrift").msgclass 59 | RTPStats = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTPStats").msgclass 60 | RTCPSenderReportState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTCPSenderReportState").msgclass 61 | RTPForwarderState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTPForwarderState").msgclass 62 | RTPMungerState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTPMungerState").msgclass 63 | VP8MungerState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VP8MungerState").msgclass 64 | TimedVersion = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TimedVersion").msgclass 65 | DataStream = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream").msgclass 66 | DataStream::TextHeader = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.TextHeader").msgclass 67 | DataStream::ByteHeader = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.ByteHeader").msgclass 68 | DataStream::Header = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.Header").msgclass 69 | DataStream::Chunk = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.Chunk").msgclass 70 | DataStream::Trailer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.Trailer").msgclass 71 | DataStream::OperationType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.OperationType").enummodule 72 | WebhookConfig = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.WebhookConfig").msgclass 73 | SubscribedAudioCodec = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SubscribedAudioCodec").msgclass 74 | AudioCodec = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AudioCodec").enummodule 75 | VideoCodec = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VideoCodec").enummodule 76 | ImageCodec = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ImageCodec").enummodule 77 | BackupCodecPolicy = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.BackupCodecPolicy").enummodule 78 | TrackType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TrackType").enummodule 79 | TrackSource = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TrackSource").enummodule 80 | VideoQuality = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VideoQuality").enummodule 81 | ConnectionQuality = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ConnectionQuality").enummodule 82 | ClientConfigSetting = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ClientConfigSetting").enummodule 83 | DisconnectReason = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DisconnectReason").enummodule 84 | ReconnectReason = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ReconnectReason").enummodule 85 | SubscriptionError = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SubscriptionError").enummodule 86 | AudioTrackFeature = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AudioTrackFeature").enummodule 87 | end 88 | end 89 | --------------------------------------------------------------------------------