├── .editorconfig
├── .github
├── banner_dark.png
├── banner_light.png
└── workflows
│ └── test.yml
├── .gitignore
├── .gitmodules
├── .rspec
├── .rubocop.yml
├── .rubocop_todo.yml
├── .ruby-version
├── .tool-versions
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── NOTICE
├── README.md
├── Rakefile
├── bin
├── bootstrap.sh
├── bundle
├── coderay
├── console
├── htmldiff
├── ldiff
├── pry
├── rake
├── rspec
├── rubocop
├── ruby-parse
├── ruby-rewrite
├── yard
├── yardoc
└── yri
├── lib
├── livekit.rb
└── livekit
│ ├── access_token.rb
│ ├── agent_dispatch_service_client.rb
│ ├── auth_mixin.rb
│ ├── egress_service_client.rb
│ ├── grants.rb
│ ├── ingress_service_client.rb
│ ├── proto
│ ├── livekit_agent_dispatch_pb.rb
│ ├── livekit_agent_dispatch_twirp.rb
│ ├── livekit_agent_pb.rb
│ ├── livekit_agent_twirp.rb
│ ├── livekit_egress_pb.rb
│ ├── livekit_egress_twirp.rb
│ ├── livekit_ingress_pb.rb
│ ├── livekit_ingress_twirp.rb
│ ├── livekit_metrics_pb.rb
│ ├── livekit_metrics_twirp.rb
│ ├── livekit_models_pb.rb
│ ├── livekit_models_twirp.rb
│ ├── livekit_room_pb.rb
│ ├── livekit_room_twirp.rb
│ ├── livekit_sip_pb.rb
│ ├── livekit_sip_twirp.rb
│ ├── livekit_webhook_pb.rb
│ └── livekit_webhook_twirp.rb
│ ├── room_service_client.rb
│ ├── sip_service_client.rb
│ ├── token_verifier.rb
│ ├── utils.rb
│ └── version.rb
├── livekit_server_sdk.gemspec
└── spec
├── livekit
├── access_token_spec.rb
├── core_spec.rb
├── grants_spec.rb
└── token_verifier_spec.rb
└── spec_helper.rb
/.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 |
--------------------------------------------------------------------------------
/.github/banner_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/livekit/server-sdk-ruby/75f2efb7186e4e0f4fe551b08cc5ede091cafb3f/.github/banner_dark.png
--------------------------------------------------------------------------------
/.github/banner_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/livekit/server-sdk-ruby/75f2efb7186e4e0f4fe551b08cc5ede091cafb3f/.github/banner_light.png
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "protocol"]
2 | path = protocol
3 | url = https://github.com/livekit/protocol
4 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --format documentation
2 | --color
3 | --require spec_helper
4 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [Unreleased]
2 |
3 | ## [0.1.0] - 2021-07-25
4 |
5 | - Initial release
6 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8 |
9 | ## Our Standards
10 |
11 | Examples of behavior that contributes to a positive environment for our community include:
12 |
13 | * Demonstrating empathy and kindness toward other people
14 | * Being respectful of differing opinions, viewpoints, and experiences
15 | * Giving and gracefully accepting constructive feedback
16 | * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17 | * Focusing on what is best not just for us as individuals, but for the overall community
18 |
19 | Examples of unacceptable behavior include:
20 |
21 | * The use of sexualized language or imagery, and sexual attention or
22 | advances of any kind
23 | * Trolling, insulting or derogatory comments, and personal or political attacks
24 | * Public or private harassment
25 | * Publishing others' private information, such as a physical or email
26 | address, without their explicit permission
27 | * Other conduct which could reasonably be considered inappropriate in a
28 | professional setting
29 |
30 | ## Enforcement Responsibilities
31 |
32 | Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
33 |
34 | Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
35 |
36 | ## Scope
37 |
38 | This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
39 |
40 | ## Enforcement
41 |
42 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at omri.gabay@pnmac.com. All complaints will be reviewed and investigated promptly and fairly.
43 |
44 | All community leaders are obligated to respect the privacy and security of the reporter of any incident.
45 |
46 | ## Enforcement Guidelines
47 |
48 | Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
49 |
50 | ### 1. Correction
51 |
52 | **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
53 |
54 | **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
55 |
56 | ### 2. Warning
57 |
58 | **Community Impact**: A violation through a single incident or series of actions.
59 |
60 | **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
61 |
62 | ### 3. Temporary Ban
63 |
64 | **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
65 |
66 | **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
67 |
68 | ### 4. Permanent Ban
69 |
70 | **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
71 |
72 | **Consequence**: A permanent ban from any sort of public interaction within the community.
73 |
74 | ## Attribution
75 |
76 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
77 | available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
78 |
79 | Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
80 |
81 | [homepage]: https://www.contributor-covenant.org
82 |
83 | For answers to common questions about this code of conduct, see the FAQ at
84 | https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
85 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: .
3 | specs:
4 | livekit-server-sdk (0.8.3)
5 | google-protobuf (>= 3.21.0, < 4.0)
6 | jwt (>= 2.2.3, < 3.0)
7 | rack (>= 2.2.3)
8 | twirp (>= 1.10.0, < 2.0)
9 |
10 | GEM
11 | remote: https://rubygems.org/
12 | specs:
13 | base64 (0.2.0)
14 | coderay (1.1.3)
15 | diff-lcs (1.5.0)
16 | faraday (2.10.1)
17 | faraday-net_http (>= 2.0, < 3.2)
18 | logger
19 | faraday-net_http (3.1.1)
20 | net-http
21 | google-protobuf (3.25.4)
22 | jwt (2.8.2)
23 | base64
24 | logger (1.6.5)
25 | method_source (1.0.0)
26 | net-http (0.4.1)
27 | uri
28 | pry (0.14.2)
29 | coderay (~> 1.1)
30 | method_source (~> 1.0)
31 | pry-doc (1.4.0)
32 | pry (~> 0.11)
33 | yard (~> 0.9.11)
34 | rack (3.1.7)
35 | rake (13.0.6)
36 | rspec (3.12.0)
37 | rspec-core (~> 3.12.0)
38 | rspec-expectations (~> 3.12.0)
39 | rspec-mocks (~> 3.12.0)
40 | rspec-core (3.12.1)
41 | rspec-support (~> 3.12.0)
42 | rspec-expectations (3.12.2)
43 | diff-lcs (>= 1.2.0, < 2.0)
44 | rspec-support (~> 3.12.0)
45 | rspec-mocks (3.12.3)
46 | diff-lcs (>= 1.2.0, < 2.0)
47 | rspec-support (~> 3.12.0)
48 | rspec-support (3.12.0)
49 | twirp (1.10.0)
50 | faraday (< 3)
51 | google-protobuf (~> 3.0, >= 3.7.0)
52 | uri (0.13.0)
53 | webrick (1.7.0)
54 | yard (0.9.28)
55 | webrick (~> 1.7.0)
56 |
57 | PLATFORMS
58 | ruby
59 | x86_64-linux
60 |
61 | DEPENDENCIES
62 | livekit-server-sdk!
63 | pry
64 | pry-doc
65 | rake
66 | rspec
67 | yard
68 |
69 | BUNDLED WITH
70 | 2.3.7
71 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
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 |
150 |
151 |
--------------------------------------------------------------------------------
/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/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | echo "Ensure protoc and Go are installed"
4 |
5 | go install github.com/github/twirp-ruby/protoc-gen-twirp_ruby@latest
6 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/lib/livekit/grants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module LiveKit
4 | class ClaimGrant
5 | attr_accessor :identity, :name, :metadata, :sha256, :video, :sip, :attributes, :room_preset, :room_config
6 |
7 | def self.from_hash(hash)
8 | return nil if hash.nil?
9 |
10 | claim_grant = ClaimGrant.new
11 | claim_grant.identity = hash["sub"]
12 | claim_grant.name = hash["name"]
13 | claim_grant.metadata = hash["metadata"]
14 | claim_grant.attributes = hash["attributes"]
15 | claim_grant.sha256 = hash["sha256"]
16 | claim_grant.video = VideoGrant.from_hash(hash["video"])
17 | claim_grant.sip = SIPGrant.from_hash(hash["sip"])
18 | claim_grant.room_preset = hash["roomPreset"]
19 | if hash["roomConfig"]
20 | # re-hydrate from JSON to ensure it can parse camelCase fields correctly
21 | claim_grant.room_config = Proto::RoomConfiguration.decode_json(hash["roomConfig"].to_json)
22 | end
23 | return claim_grant
24 | end
25 |
26 | def initialize
27 | @identity = nil
28 | @name = nil
29 | @metadata = nil
30 | @sha256 = nil
31 | @video = nil
32 | @sip = nil
33 | @attributes = nil
34 | @room_preset = nil
35 | @room_config = nil
36 | end
37 |
38 | def to_hash
39 | val = {
40 | name: @name,
41 | metadata: @metadata,
42 | attributes: @attributes,
43 | sha256: @sha256,
44 | }
45 | if @video
46 | val[:video] = @video.to_hash
47 | end
48 | if @sip
49 | val[:sip] = @sip.to_hash
50 | end
51 | if @room_preset
52 | val[:roomPreset] = @room_preset
53 | end
54 | if @room_config
55 | val[:roomConfig] = JSON.parse(@room_config.to_json)
56 | end
57 | return val
58 | end
59 | end
60 |
61 | class VideoGrant
62 | using LiveKit::Utils::StringifyKeysRefinement
63 |
64 | attr_accessor :roomCreate, :roomJoin, :roomList, :roomRecord, :roomAdmin,
65 | :room, :canPublish, :canPublishSources, :canSubscribe, :canPublishData,
66 | :canUpdateOwnMetadata, :hidden, :recorder, :ingressAdmin
67 |
68 | def initialize(
69 | # true if can create or delete rooms
70 | roomCreate: nil,
71 | # true if can join room
72 | roomJoin: nil,
73 | # true if can list rooms
74 | roomList: nil,
75 | # true if can record
76 | roomRecord: nil,
77 | # true if can manage the room
78 | roomAdmin: nil,
79 | # name of the room for join or admin permissions
80 | room: nil,
81 | # for join tokens, can participant publish, true by default
82 | canPublish: nil,
83 | # TrackSource types that a participant may publish
84 | canPublishSources: nil,
85 | # for join tokens, can participant subscribe, true by default
86 | canSubscribe: nil,
87 | # for join tokens, can participant publish data messages, true by default
88 | canPublishData: nil,
89 | # by default, a participant is not allowed to update its own metadata
90 | canUpdateOwnMetadata: nil,
91 | # if participant should remain invisible to others
92 | hidden: nil,
93 | # if participant is recording the room
94 | recorder: nil,
95 | # can create and manage Ingress
96 | ingressAdmin: nil
97 | )
98 | @roomCreate = roomCreate
99 | @roomJoin = roomJoin
100 | @roomList = roomList
101 | @roomRecord = roomRecord
102 | @roomAdmin = roomAdmin
103 | @room = room
104 | @canPublish = canPublish
105 | @canPublishSources = canPublishSources
106 | @canSubscribe = canSubscribe
107 | @canPublishData = canPublishData
108 | @canUpdateOwnMetadata = canUpdateOwnMetadata
109 | @hidden = hidden
110 | @recorder = recorder
111 | @ingressAdmin = ingressAdmin
112 | end
113 |
114 | def self.from_hash(hash)
115 | return nil if hash.nil?
116 |
117 | hash = hash.stringify_keys
118 |
119 | VideoGrant.new(
120 | roomCreate: hash["roomCreate"],
121 | roomJoin: hash["roomJoin"],
122 | roomList: hash["roomList"],
123 | roomRecord: hash["roomRecord"],
124 | roomAdmin: hash["roomAdmin"],
125 | room: hash["room"],
126 | canPublish: hash["canPublish"],
127 | canPublishSources: hash["canPublishSources"],
128 | canSubscribe: hash["canSubscribe"],
129 | canPublishData: hash["canPublishData"],
130 | canUpdateOwnMetadata: hash["canUpdateOwnMetadata"],
131 | hidden: hash["hidden"],
132 | recorder: hash["recorder"],
133 | ingressAdmin: hash["ingressAdmin"]
134 | )
135 | end
136 |
137 | def to_hash
138 | hash = {}
139 | instance_variables.each { |var|
140 | val = instance_variable_get(var)
141 | if val != nil
142 | hash[var.to_s.delete("@")] = val
143 | end
144 | }
145 | hash
146 | end
147 | end
148 |
149 | class SIPGrant
150 | using LiveKit::Utils::StringifyKeysRefinement
151 |
152 | attr_accessor :admin, :call
153 |
154 | def initialize(
155 | # true if can access SIP features
156 | admin: nil,
157 | # true if can make outgoing call
158 | call: nil
159 | )
160 | @admin = admin
161 | @call = call
162 | end
163 |
164 | def self.from_hash(hash)
165 | return nil if hash.nil?
166 |
167 | hash = hash.stringify_keys
168 |
169 | SIPGrant.new(
170 | admin: hash["admin"],
171 | call: hash["call"]
172 | )
173 | end
174 |
175 | def to_hash
176 | hash = {}
177 | instance_variables.each { |var|
178 | val = instance_variable_get(var)
179 | if val != nil
180 | hash[var.to_s.delete("@")] = val
181 | end
182 | }
183 | hash
184 | end
185 | end
186 | end
187 |
--------------------------------------------------------------------------------
/lib/livekit/ingress_service_client.rb:
--------------------------------------------------------------------------------
1 | require "livekit/proto/livekit_ingress_twirp"
2 | require "livekit/auth_mixin"
3 | require 'livekit/utils'
4 |
5 | module LiveKit
6 | class IngressServiceClient < Twirp::Client
7 | client_for Proto::IngressService
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_ingress(
18 | input_type,
19 | # optional, name to identify the ingress
20 | name: nil,
21 | # optional, you can attach to a room at a later time
22 | room_name: nil,
23 | # optional, identity of participant to publish as
24 | participant_identity: nil,
25 | # optional, display name of participant
26 | participant_name: nil,
27 | # optional, LiveKit::Proto::IngressAudioOptions
28 | audio: nil,
29 | # optional, LiveKit::Proto::IngressVideoOptions
30 | video: nil,
31 | # optional, whether to forward input media unprocessed, for WHIP only [deprecated]
32 | bypass_transcoding: nil,
33 | # optional, whether to enable transcoding or forward the input media directly.
34 | # Transcoding is required for all input types except WHIP. For WHIP, the default is to not transcode.
35 | enable_transcoding: nil,
36 | # optional, needed for ingresses of type URL, provides the URL to fetch media from
37 | url: nil
38 | )
39 | request = Proto::CreateIngressRequest.new(
40 | input_type: input_type,
41 | name: name,
42 | room_name: room_name,
43 | participant_identity: participant_identity,
44 | participant_name: participant_name,
45 | audio: audio,
46 | video: video,
47 | bypass_transcoding: bypass_transcoding,
48 | enable_transcoding: enable_transcoding,
49 | url: url,
50 | )
51 | self.rpc(
52 | :CreateIngress,
53 | request,
54 | headers:auth_header(video_grant: VideoGrant.new(ingressAdmin: true)),
55 | )
56 | end
57 |
58 | def update_ingress(
59 | ingress_id,
60 | # optional, name to identify the ingress
61 | name: nil,
62 | # optional, you can attach to a room at a later time
63 | room_name: nil,
64 | # optional, identity of participant to publish as
65 | participant_identity: nil,
66 | # optional, display name of participant
67 | participant_name: nil,
68 | # optional, LiveKit::Proto::IngressAudioOptions
69 | audio: nil,
70 | # optional, LiveKit::Proto::IngressVideoOptions
71 | video: nil,
72 | # optional, whether to forward input media unprocessed, for WHIP only
73 | bypass_transcoding: nil,
74 | # optional, whether to enable transcoding or forward the input media directly.
75 | # Transcoding is required for all input types except WHIP. For WHIP, the default is to not transcode.
76 | enable_transcoding: nil
77 | )
78 | request = Proto::UpdateIngressRequest.new(
79 | ingress_id: ingress_id,
80 | name: name,
81 | room_name: room_name,
82 | participant_identity: participant_identity,
83 | participant_name: participant_name,
84 | audio: audio,
85 | video: video,
86 | bypass_transcoding: bypass_transcoding,
87 | enable_transcoding: enable_transcoding,
88 | )
89 | self.rpc(
90 | :UpdateIngress,
91 | request,
92 | headers:auth_header(video_grant: VideoGrant.new(ingressAdmin: true)),
93 | )
94 | end
95 |
96 | def list_ingress(
97 | # optional, filter by room name
98 | room_name: nil,
99 | # optional, list by ingress id
100 | ingress_id: nil
101 | )
102 | request = Proto::ListIngressRequest.new(
103 | room_name: room_name,
104 | ingress_id: ingress_id,
105 | )
106 | self.rpc(
107 | :ListIngress,
108 | request,
109 | headers:auth_header(video_grant: VideoGrant.new(ingressAdmin: true)),
110 | )
111 | end
112 |
113 | def delete_ingress(ingress_id)
114 | request = Proto::DeleteIngressRequest.new(
115 | ingress_id: ingress_id
116 | )
117 | self.rpc(
118 | :DeleteIngress,
119 | request,
120 | headers:auth_header(video_grant: VideoGrant.new(ingressAdmin: true)),
121 | )
122 | end
123 | end
124 | end
125 |
--------------------------------------------------------------------------------
/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/proto/livekit_agent_dispatch_twirp.rb:
--------------------------------------------------------------------------------
1 | # Code generated by protoc-gen-twirp_ruby 1.10.0, 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_agent_pb.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Generated by the protocol buffer compiler. DO NOT EDIT!
3 | # source: livekit_agent.proto
4 |
5 | require 'google/protobuf'
6 |
7 | require 'livekit_models_pb'
8 |
9 |
10 | descriptor_data = "\n\x13livekit_agent.proto\x12\x07livekit\x1a\x14livekit_models.proto\"\x86\x02\n\x03Job\x12\n\n\x02id\x18\x01 \x01(\t\x12\x13\n\x0b\x64ispatch_id\x18\t \x01(\t\x12\x1e\n\x04type\x18\x02 \x01(\x0e\x32\x10.livekit.JobType\x12\x1b\n\x04room\x18\x03 \x01(\x0b\x32\r.livekit.Room\x12\x32\n\x0bparticipant\x18\x04 \x01(\x0b\x32\x18.livekit.ParticipantInfoH\x00\x88\x01\x01\x12\x15\n\tnamespace\x18\x05 \x01(\tB\x02\x18\x01\x12\x10\n\x08metadata\x18\x06 \x01(\t\x12\x12\n\nagent_name\x18\x07 \x01(\t\x12 \n\x05state\x18\x08 \x01(\x0b\x32\x11.livekit.JobStateB\x0e\n\x0c_participant\"\x95\x01\n\x08JobState\x12\"\n\x06status\x18\x01 \x01(\x0e\x32\x12.livekit.JobStatus\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x12\n\nstarted_at\x18\x03 \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x04 \x01(\x03\x12\x12\n\nupdated_at\x18\x05 \x01(\x03\x12\x1c\n\x14participant_identity\x18\x06 \x01(\t\"\xf8\x02\n\rWorkerMessage\x12\x32\n\x08register\x18\x01 \x01(\x0b\x32\x1e.livekit.RegisterWorkerRequestH\x00\x12\x35\n\x0c\x61vailability\x18\x02 \x01(\x0b\x32\x1d.livekit.AvailabilityResponseH\x00\x12\x34\n\rupdate_worker\x18\x03 \x01(\x0b\x32\x1b.livekit.UpdateWorkerStatusH\x00\x12.\n\nupdate_job\x18\x04 \x01(\x0b\x32\x18.livekit.UpdateJobStatusH\x00\x12#\n\x04ping\x18\x05 \x01(\x0b\x32\x13.livekit.WorkerPingH\x00\x12\x33\n\x0csimulate_job\x18\x06 \x01(\x0b\x32\x1b.livekit.SimulateJobRequestH\x00\x12\x31\n\x0bmigrate_job\x18\x07 \x01(\x0b\x32\x1a.livekit.MigrateJobRequestH\x00\x42\t\n\x07message\"\x88\x02\n\rServerMessage\x12\x33\n\x08register\x18\x01 \x01(\x0b\x32\x1f.livekit.RegisterWorkerResponseH\x00\x12\x34\n\x0c\x61vailability\x18\x02 \x01(\x0b\x32\x1c.livekit.AvailabilityRequestH\x00\x12,\n\nassignment\x18\x03 \x01(\x0b\x32\x16.livekit.JobAssignmentH\x00\x12.\n\x0btermination\x18\x05 \x01(\x0b\x32\x17.livekit.JobTerminationH\x00\x12#\n\x04pong\x18\x04 \x01(\x0b\x32\x13.livekit.WorkerPongH\x00\x42\t\n\x07message\"\x80\x01\n\x12SimulateJobRequest\x12\x1e\n\x04type\x18\x01 \x01(\x0e\x32\x10.livekit.JobType\x12\x1b\n\x04room\x18\x02 \x01(\x0b\x32\r.livekit.Room\x12-\n\x0bparticipant\x18\x03 \x01(\x0b\x32\x18.livekit.ParticipantInfo\"\x1f\n\nWorkerPing\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\"7\n\nWorkerPong\x12\x16\n\x0elast_timestamp\x18\x01 \x01(\x03\x12\x11\n\ttimestamp\x18\x02 \x01(\x03\"\xd6\x01\n\x15RegisterWorkerRequest\x12\x1e\n\x04type\x18\x01 \x01(\x0e\x32\x10.livekit.JobType\x12\x12\n\nagent_name\x18\x08 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x15\n\rping_interval\x18\x05 \x01(\r\x12\x16\n\tnamespace\x18\x06 \x01(\tH\x00\x88\x01\x01\x12;\n\x13\x61llowed_permissions\x18\x07 \x01(\x0b\x32\x1e.livekit.ParticipantPermissionB\x0c\n\n_namespace\"U\n\x16RegisterWorkerResponse\x12\x11\n\tworker_id\x18\x01 \x01(\t\x12(\n\x0bserver_info\x18\x03 \x01(\x0b\x32\x13.livekit.ServerInfo\"$\n\x11MigrateJobRequest\x12\x0f\n\x07job_ids\x18\x02 \x03(\t\"B\n\x13\x41vailabilityRequest\x12\x19\n\x03job\x18\x01 \x01(\x0b\x32\x0c.livekit.Job\x12\x10\n\x08resuming\x18\x02 \x01(\x08\"\xc0\x02\n\x14\x41vailabilityResponse\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\x11\n\tavailable\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_resume\x18\x03 \x01(\x08\x12\x18\n\x10participant_name\x18\x04 \x01(\t\x12\x1c\n\x14participant_identity\x18\x05 \x01(\t\x12\x1c\n\x14participant_metadata\x18\x06 \x01(\t\x12X\n\x16participant_attributes\x18\x07 \x03(\x0b\x32\x38.livekit.AvailabilityResponse.ParticipantAttributesEntry\x1a<\n\x1aParticipantAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"T\n\x0fUpdateJobStatus\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\"\n\x06status\x18\x02 \x01(\x0e\x32\x12.livekit.JobStatus\x12\r\n\x05\x65rror\x18\x03 \x01(\t\"l\n\x12UpdateWorkerStatus\x12*\n\x06status\x18\x01 \x01(\x0e\x32\x15.livekit.WorkerStatusH\x00\x88\x01\x01\x12\x0c\n\x04load\x18\x03 \x01(\x02\x12\x11\n\tjob_count\x18\x04 \x01(\rB\t\n\x07_status\"S\n\rJobAssignment\x12\x19\n\x03job\x18\x01 \x01(\x0b\x32\x0c.livekit.Job\x12\x10\n\x03url\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\r\n\x05token\x18\x03 \x01(\tB\x06\n\x04_url\" \n\x0eJobTermination\x12\x0e\n\x06job_id\x18\x01 \x01(\t*(\n\x07JobType\x12\x0b\n\x07JT_ROOM\x10\x00\x12\x10\n\x0cJT_PUBLISHER\x10\x01*-\n\x0cWorkerStatus\x12\x10\n\x0cWS_AVAILABLE\x10\x00\x12\x0b\n\x07WS_FULL\x10\x01*J\n\tJobStatus\x12\x0e\n\nJS_PENDING\x10\x00\x12\x0e\n\nJS_RUNNING\x10\x01\x12\x0e\n\nJS_SUCCESS\x10\x02\x12\r\n\tJS_FAILED\x10\x03\x42\x46Z#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 | Job = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Job").msgclass
18 | JobState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobState").msgclass
19 | WorkerMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.WorkerMessage").msgclass
20 | ServerMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ServerMessage").msgclass
21 | SimulateJobRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SimulateJobRequest").msgclass
22 | WorkerPing = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.WorkerPing").msgclass
23 | WorkerPong = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.WorkerPong").msgclass
24 | RegisterWorkerRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RegisterWorkerRequest").msgclass
25 | RegisterWorkerResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RegisterWorkerResponse").msgclass
26 | MigrateJobRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.MigrateJobRequest").msgclass
27 | AvailabilityRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AvailabilityRequest").msgclass
28 | AvailabilityResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AvailabilityResponse").msgclass
29 | UpdateJobStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateJobStatus").msgclass
30 | UpdateWorkerStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateWorkerStatus").msgclass
31 | JobAssignment = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobAssignment").msgclass
32 | JobTermination = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobTermination").msgclass
33 | JobType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobType").enummodule
34 | WorkerStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.WorkerStatus").enummodule
35 | JobStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobStatus").enummodule
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/livekit/proto/livekit_agent_twirp.rb:
--------------------------------------------------------------------------------
1 | # Code generated by protoc-gen-twirp_ruby 1.10.0, 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_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\"\xcd\x04\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\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.ImageOutputB\x08\n\x06outputB\t\n\x07options\"\xb0\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.ImageOutputB\x08\n\x06outputB\t\n\x07options\"\x85\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.ImageOutputB\t\n\x07options\"\xad\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.ImageOutputB\x08\n\x06outputB\t\n\x07options\"\x87\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\x42\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\"\xc8\x02\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\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*9\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*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*E\n\x0fImageFileSuffix\x12\x16\n\x12IMAGE_SUFFIX_INDEX\x10\x00\x12\x1a\n\x16IMAGE_SUFFIX_TIMESTAMP\x10\x01*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*\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 | EncodingOptionsPreset = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EncodingOptionsPreset").enummodule
53 | EgressStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EgressStatus").enummodule
54 | EgressSourceType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.EgressSourceType").enummodule
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/lib/livekit/proto/livekit_egress_twirp.rb:
--------------------------------------------------------------------------------
1 | # Code generated by protoc-gen-twirp_ruby 1.10.0, 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 |
--------------------------------------------------------------------------------
/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/proto/livekit_ingress_twirp.rb:
--------------------------------------------------------------------------------
1 | # Code generated by protoc-gen-twirp_ruby 1.10.0, 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 |
--------------------------------------------------------------------------------
/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*\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\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\"3\n\nEncryption\"%\n\x04Type\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03GCM\x10\x01\x12\n\n\x06\x43USTOM\x10\x02\"f\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\"\xae\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\x11\n\tsimulcast\x18\x07 \x01(\x08\x12\x13\n\x0b\x64isable_dtx\x18\x08 \x01(\x08\x12$\n\x06source\x18\t \x01(\x0e\x32\x14.livekit.TrackSource\x12#\n\x06layers\x18\n \x03(\x0b\x32\x13.livekit.VideoLayer\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\x0e\n\x06stereo\x18\x0e \x01(\x08\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\"r\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\"\xc6\x05\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\"\x1f\n\x04Kind\x12\x0c\n\x08RELIABLE\x10\x00\x12\t\n\x05LOSSY\x10\x01\x42\x07\n\x05value\"=\n\x13\x41\x63tiveSpeakerUpdate\x12&\n\x08speakers\x18\x01 \x03(\x0b\x32\x14.livekit.SpeakerInfo\"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\"\x8a\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\"\x9c\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\"\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\"\xc5\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\xa2\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\x31\n\x0f\x65ncryption_type\x18\x07 \x01(\x0e\x32\x18.livekit.Encryption.Type\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\x1ai\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\x0f\n\x02iv\x18\x05 \x01(\x0cH\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*/\n\nAudioCodec\x12\x0e\n\nDEFAULT_AC\x10\x00\x12\x08\n\x04OPUS\x10\x01\x12\x07\n\x03\x41\x41\x43\x10\x02*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*2\n\x11\x42\x61\x63kupCodecPolicy\x12\x0e\n\nREGRESSION\x10\x00\x12\r\n\tSIMULCAST\x10\x01*+\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*\xac\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*\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*\xa3\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\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 | Room = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Room").msgclass
20 | Codec = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Codec").msgclass
21 | PlayoutDelay = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.PlayoutDelay").msgclass
22 | ParticipantPermission = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantPermission").msgclass
23 | ParticipantInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantInfo").msgclass
24 | ParticipantInfo::State = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantInfo.State").enummodule
25 | ParticipantInfo::Kind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantInfo.Kind").enummodule
26 | Encryption = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Encryption").msgclass
27 | Encryption::Type = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Encryption.Type").enummodule
28 | SimulcastCodecInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SimulcastCodecInfo").msgclass
29 | TrackInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TrackInfo").msgclass
30 | VideoLayer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VideoLayer").msgclass
31 | DataPacket = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataPacket").msgclass
32 | DataPacket::Kind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataPacket.Kind").enummodule
33 | ActiveSpeakerUpdate = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ActiveSpeakerUpdate").msgclass
34 | SpeakerInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SpeakerInfo").msgclass
35 | UserPacket = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UserPacket").msgclass
36 | SipDTMF = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SipDTMF").msgclass
37 | Transcription = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.Transcription").msgclass
38 | TranscriptionSegment = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TranscriptionSegment").msgclass
39 | ChatMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ChatMessage").msgclass
40 | RpcRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RpcRequest").msgclass
41 | RpcAck = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RpcAck").msgclass
42 | RpcResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RpcResponse").msgclass
43 | RpcError = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RpcError").msgclass
44 | ParticipantTracks = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ParticipantTracks").msgclass
45 | ServerInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ServerInfo").msgclass
46 | ServerInfo::Edition = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ServerInfo.Edition").enummodule
47 | ClientInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ClientInfo").msgclass
48 | ClientInfo::SDK = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ClientInfo.SDK").enummodule
49 | ClientConfiguration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ClientConfiguration").msgclass
50 | VideoConfiguration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VideoConfiguration").msgclass
51 | DisabledCodecs = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DisabledCodecs").msgclass
52 | RTPDrift = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTPDrift").msgclass
53 | RTPStats = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTPStats").msgclass
54 | RTCPSenderReportState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTCPSenderReportState").msgclass
55 | RTPForwarderState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTPForwarderState").msgclass
56 | RTPMungerState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.RTPMungerState").msgclass
57 | VP8MungerState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VP8MungerState").msgclass
58 | TimedVersion = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TimedVersion").msgclass
59 | DataStream = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream").msgclass
60 | DataStream::TextHeader = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.TextHeader").msgclass
61 | DataStream::ByteHeader = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.ByteHeader").msgclass
62 | DataStream::Header = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.Header").msgclass
63 | DataStream::Chunk = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.Chunk").msgclass
64 | DataStream::Trailer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.Trailer").msgclass
65 | DataStream::OperationType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DataStream.OperationType").enummodule
66 | AudioCodec = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AudioCodec").enummodule
67 | VideoCodec = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VideoCodec").enummodule
68 | ImageCodec = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ImageCodec").enummodule
69 | BackupCodecPolicy = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.BackupCodecPolicy").enummodule
70 | TrackType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TrackType").enummodule
71 | TrackSource = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TrackSource").enummodule
72 | VideoQuality = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.VideoQuality").enummodule
73 | ConnectionQuality = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ConnectionQuality").enummodule
74 | ClientConfigSetting = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ClientConfigSetting").enummodule
75 | DisconnectReason = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DisconnectReason").enummodule
76 | ReconnectReason = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ReconnectReason").enummodule
77 | SubscriptionError = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SubscriptionError").enummodule
78 | AudioTrackFeature = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AudioTrackFeature").enummodule
79 | end
80 | end
81 |
--------------------------------------------------------------------------------
/lib/livekit/proto/livekit_models_twirp.rb:
--------------------------------------------------------------------------------
1 | # Code generated by protoc-gen-twirp_ruby 1.10.0, 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_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\"\x8a\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#\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.RoomAgentDispatch2\xe6\x06\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.RoomBFZ#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 | end
40 | end
41 |
--------------------------------------------------------------------------------
/lib/livekit/proto/livekit_room_twirp.rb:
--------------------------------------------------------------------------------
1 | # Code generated by protoc-gen-twirp_ruby 1.10.0, 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 | end
22 |
23 | class RoomServiceClient < ::Twirp::Client
24 | client_for RoomServiceService
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/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/duration_pb'
8 | require 'google/protobuf/empty_pb'
9 | require 'livekit_models_pb'
10 | require 'livekit_room_pb'
11 |
12 |
13 | descriptor_data = "\n\x11livekit_sip.proto\x12\x07livekit\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\"\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\"M\n\x1d\x43reateSIPOutboundTrunkRequest\x12,\n\x05trunk\x18\x01 \x01(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"\xc4\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(\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\"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\"\xf1\x02\n\x1c\x43reateSIPDispatchRuleRequest\x12&\n\x04rule\x18\x01 \x01(\x0b\x32\x18.livekit.SIPDispatchRule\x12\x11\n\ttrunk_ids\x18\x02 \x03(\t\x12\x19\n\x11hide_phone_number\x18\x03 \x01(\x08\x12\x17\n\x0finbound_numbers\x18\x06 \x03(\t\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x10\n\x08metadata\x18\x05 \x01(\t\x12I\n\nattributes\x18\x07 \x03(\x0b\x32\x35.livekit.CreateSIPDispatchRuleRequest.AttributesEntry\x12\x13\n\x0broom_preset\x18\x08 \x01(\t\x12/\n\x0broom_config\x18\t \x01(\x0b\x32\x1a.livekit.RoomConfiguration\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\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\"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\"\xbc\x06\n\x1b\x43reateSIPParticipantRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\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\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\"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\"\xf2\x01\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\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xc4\x03\n\x0bSIPCallInfo\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x10\n\x08trunk_id\x18\x02 \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\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-\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\x12\n\ncreated_at\x18\t \x01(\x03\x12\x12\n\nstarted_at\x18\n \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x0b \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\"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*)\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\xba\t\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\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\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"
14 |
15 | pool = Google::Protobuf::DescriptorPool.generated_pool
16 | pool.add_serialized_file(descriptor_data)
17 |
18 | module LiveKit
19 | module Proto
20 | SIPStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPStatus").msgclass
21 | CreateSIPTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPTrunkRequest").msgclass
22 | SIPTrunkInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPTrunkInfo").msgclass
23 | SIPTrunkInfo::TrunkKind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPTrunkInfo.TrunkKind").enummodule
24 | CreateSIPInboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPInboundTrunkRequest").msgclass
25 | SIPInboundTrunkInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPInboundTrunkInfo").msgclass
26 | CreateSIPOutboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPOutboundTrunkRequest").msgclass
27 | SIPOutboundTrunkInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPOutboundTrunkInfo").msgclass
28 | GetSIPInboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.GetSIPInboundTrunkRequest").msgclass
29 | GetSIPInboundTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.GetSIPInboundTrunkResponse").msgclass
30 | GetSIPOutboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.GetSIPOutboundTrunkRequest").msgclass
31 | GetSIPOutboundTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.GetSIPOutboundTrunkResponse").msgclass
32 | ListSIPTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPTrunkRequest").msgclass
33 | ListSIPTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPTrunkResponse").msgclass
34 | ListSIPInboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPInboundTrunkRequest").msgclass
35 | ListSIPInboundTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPInboundTrunkResponse").msgclass
36 | ListSIPOutboundTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPOutboundTrunkRequest").msgclass
37 | ListSIPOutboundTrunkResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPOutboundTrunkResponse").msgclass
38 | DeleteSIPTrunkRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DeleteSIPTrunkRequest").msgclass
39 | SIPDispatchRuleDirect = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRuleDirect").msgclass
40 | SIPDispatchRuleIndividual = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRuleIndividual").msgclass
41 | SIPDispatchRuleCallee = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRuleCallee").msgclass
42 | SIPDispatchRule = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRule").msgclass
43 | CreateSIPDispatchRuleRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPDispatchRuleRequest").msgclass
44 | SIPDispatchRuleInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPDispatchRuleInfo").msgclass
45 | ListSIPDispatchRuleRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPDispatchRuleRequest").msgclass
46 | ListSIPDispatchRuleResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListSIPDispatchRuleResponse").msgclass
47 | DeleteSIPDispatchRuleRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.DeleteSIPDispatchRuleRequest").msgclass
48 | CreateSIPParticipantRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.CreateSIPParticipantRequest").msgclass
49 | SIPParticipantInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPParticipantInfo").msgclass
50 | TransferSIPParticipantRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TransferSIPParticipantRequest").msgclass
51 | SIPCallInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPCallInfo").msgclass
52 | SIPUri = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPUri").msgclass
53 | SIPStatusCode = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPStatusCode").enummodule
54 | SIPTransport = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPTransport").enummodule
55 | SIPHeaderOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPHeaderOptions").enummodule
56 | SIPMediaEncryption = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPMediaEncryption").enummodule
57 | SIPCallStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPCallStatus").enummodule
58 | SIPFeature = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPFeature").enummodule
59 | SIPCallDirection = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.SIPCallDirection").enummodule
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/lib/livekit/proto/livekit_sip_twirp.rb:
--------------------------------------------------------------------------------
1 | # Code generated by protoc-gen-twirp_ruby 1.10.0, 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 :GetSIPInboundTrunk, GetSIPInboundTrunkRequest, GetSIPInboundTrunkResponse, :ruby_method => :get_s_i_p_inbound_trunk
14 | rpc :GetSIPOutboundTrunk, GetSIPOutboundTrunkRequest, GetSIPOutboundTrunkResponse, :ruby_method => :get_s_i_p_outbound_trunk
15 | rpc :ListSIPInboundTrunk, ListSIPInboundTrunkRequest, ListSIPInboundTrunkResponse, :ruby_method => :list_s_i_p_inbound_trunk
16 | rpc :ListSIPOutboundTrunk, ListSIPOutboundTrunkRequest, ListSIPOutboundTrunkResponse, :ruby_method => :list_s_i_p_outbound_trunk
17 | rpc :DeleteSIPTrunk, DeleteSIPTrunkRequest, SIPTrunkInfo, :ruby_method => :delete_s_i_p_trunk
18 | rpc :CreateSIPDispatchRule, CreateSIPDispatchRuleRequest, SIPDispatchRuleInfo, :ruby_method => :create_s_i_p_dispatch_rule
19 | rpc :ListSIPDispatchRule, ListSIPDispatchRuleRequest, ListSIPDispatchRuleResponse, :ruby_method => :list_s_i_p_dispatch_rule
20 | rpc :DeleteSIPDispatchRule, DeleteSIPDispatchRuleRequest, SIPDispatchRuleInfo, :ruby_method => :delete_s_i_p_dispatch_rule
21 | rpc :CreateSIPParticipant, CreateSIPParticipantRequest, SIPParticipantInfo, :ruby_method => :create_s_i_p_participant
22 | rpc :TransferSIPParticipant, TransferSIPParticipantRequest, Google::Protobuf::Empty, :ruby_method => :transfer_s_i_p_participant
23 | end
24 |
25 | class SIPClient < ::Twirp::Client
26 | client_for SIPService
27 | end
28 | end
29 | end
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\"\x97\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\x13\n\x0bnum_dropped\x18\x0b \x01(\x05\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_webhook_twirp.rb:
--------------------------------------------------------------------------------
1 | # Code generated by protoc-gen-twirp_ruby 1.10.0, 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 |
--------------------------------------------------------------------------------
/lib/livekit/room_service_client.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'securerandom'
4 | require "livekit/proto/livekit_room_twirp"
5 | require "livekit/auth_mixin"
6 | require 'livekit/utils'
7 |
8 |
9 | module LiveKit
10 | class RoomServiceClient < Twirp::Client
11 | client_for Proto::RoomServiceService
12 | include AuthMixin
13 | attr_accessor :api_key, :api_secret
14 |
15 | def initialize(base_url, api_key: nil, api_secret: nil)
16 | super(File.join(Utils.to_http_url(base_url), "/twirp"))
17 | @api_key = api_key
18 | @api_secret = api_secret
19 | end
20 |
21 | def create_room(name,
22 | empty_timeout: nil,
23 | max_participants: nil,
24 | egress: nil,
25 | metadata: nil,
26 | min_playout_delay: nil,
27 | max_playout_delay: nil,
28 | sync_streams: nil,
29 | departure_timeout: nil
30 | )
31 | self.rpc(
32 | :CreateRoom,
33 | Proto::CreateRoomRequest.new(
34 | name: name,
35 | empty_timeout: empty_timeout,
36 | departure_timeout: departure_timeout,
37 | max_participants: max_participants,
38 | egress: egress,
39 | metadata: metadata,
40 | min_playout_delay: min_playout_delay,
41 | max_playout_delay: max_playout_delay,
42 | sync_streams: sync_streams
43 | ),
44 | headers:auth_header(video_grant: VideoGrant.new(roomCreate: true)),
45 | )
46 | end
47 |
48 | def list_rooms(names: nil)
49 | self.rpc(
50 | :ListRooms,
51 | Proto::ListRoomsRequest.new(names: names),
52 | headers:auth_header(video_grant: VideoGrant.new(roomList: true)),
53 | )
54 | end
55 |
56 | def delete_room(room:)
57 | self.rpc(
58 | :DeleteRoom,
59 | Proto::DeleteRoomRequest.new(room: room),
60 | headers:auth_header(video_grant: VideoGrant.new(roomCreate: true)),
61 | )
62 | end
63 |
64 | def update_room_metadata(room:, metadata:)
65 | self.rpc(
66 | :UpdateRoomMetadata,
67 | Proto::UpdateRoomMetadataRequest.new(room: room, metadata: metadata),
68 | headers:auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room)),
69 | )
70 | end
71 |
72 | def list_participants(room:)
73 | self.rpc(
74 | :ListParticipants,
75 | Proto::ListParticipantsRequest.new(room: room),
76 | headers:auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room)),
77 | )
78 | end
79 |
80 | def get_participant(room:, identity:)
81 | self.rpc(
82 | :GetParticipant,
83 | Proto::RoomParticipantIdentity.new(room: room, identity: identity),
84 | headers:auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room)),
85 | )
86 | end
87 |
88 | def remove_participant(room:, identity:)
89 | self.rpc(
90 | :RemoveParticipant,
91 | Proto::RoomParticipantIdentity.new(room: room, identity: identity),
92 | headers:auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room)),
93 | )
94 | end
95 |
96 | def mute_published_track(room:, identity:, track_sid:, muted:)
97 | self.rpc(
98 | :MutePublishedTrack,
99 | Proto::MuteRoomTrackRequest.new(
100 | room: room,
101 | identity: identity,
102 | track_sid: track_sid,
103 | muted: muted,
104 | ),
105 | headers:auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room)),
106 | )
107 | end
108 |
109 | def update_participant(
110 | room:,
111 | identity:,
112 | metadata: nil,
113 | permission: nil,
114 | name: nil,
115 | attributes: nil
116 | )
117 | req = Proto::UpdateParticipantRequest.new(room: room, identity: identity)
118 | if metadata
119 | req.metadata = metadata
120 | end
121 | if permission
122 | req.permission = permission
123 | end
124 | if name
125 | req.name = name
126 | end
127 | if attributes
128 | attr_map = Google::Protobuf::Map.new(:string, :string)
129 | attributes.each do |k, v|
130 | attr_map[k.to_s] = v.to_s
131 | end
132 | req.attributes = attr_map
133 | end
134 | self.rpc(
135 | :UpdateParticipant,
136 | req,
137 | headers:auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room)),
138 | )
139 | end
140 |
141 | def update_subscriptions(room:, identity:, track_sids:, subscribe:)
142 | self.rpc(
143 | :UpdateSubscriptions,
144 | Proto::UpdateSubscriptionsRequest.new(
145 | room: room,
146 | identity: identity,
147 | track_sids: track_sids,
148 | subscribe: subscribe,
149 | ),
150 | headers:auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room)),
151 | )
152 | end
153 |
154 | def send_data(room:, data:, kind:,
155 | destination_sids: [],
156 | destination_identities: []
157 | )
158 | self.rpc(
159 | :SendData,
160 | Proto::SendDataRequest.new(
161 | room: room,
162 | data: data,
163 | kind: kind,
164 | destination_sids: destination_sids,
165 | destination_identities: destination_identities,
166 | nonce: SecureRandom.random_bytes(16)
167 | ),
168 | headers:auth_header(video_grant: VideoGrant.new(roomAdmin: true, room: room)),
169 | )
170 | end
171 | end
172 | end
173 |
--------------------------------------------------------------------------------
/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/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/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
--------------------------------------------------------------------------------
/lib/livekit/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module LiveKit
4 | VERSION = "0.8.3"
5 | end
6 |
--------------------------------------------------------------------------------
/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", ">= 3.21.0", "< 4.0"
30 | spec.add_dependency "jwt", ">= 2.2.3", "< 3.0"
31 | # workaround for twirp 1.10.0 missing it
32 | spec.add_dependency 'rack', '>= 2.2.3'
33 | spec.add_dependency "twirp", ">= 1.10.0", "< 2.0"
34 |
35 | # For more information and examples about making a new gem, checkout our
36 | # guide at: https://bundler.io/guides/creating_gem.html
37 | end
38 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------