Skip to content

Commit

Permalink
feat: initial monorepo & server sdk (#61)
Browse files Browse the repository at this point in the history
Co-authored-by: David Zhao <[email protected]>
  • Loading branch information
theomonnom and davidzhao authored Oct 3, 2023
1 parent 15934c5 commit 907be69
Show file tree
Hide file tree
Showing 70 changed files with 4,510 additions and 162 deletions.
4 changes: 3 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
**/*.dll filter=lfs diff=lfs merge=lfs -text
**/*.so filter=lfs diff=lfs merge=lfs -text
**/*.dylib filter=lfs diff=lfs merge=lfs -text
**/*.dylib filter=lfs diff=lfs merge=lfs -text
livekit-api/livekit/api/_proto/** linguist-generated=true
livekit-rtc/livekit/rtc/_proto/** linguist-generated=true
63 changes: 63 additions & 0 deletions .github/workflows/build-api.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Build API

on:
push:
paths:
- livekit-api/**
pull_request:
paths:
- livekit-api/**
workflow_dispatch:

env:
PACKAGE_DIR: ./livekit-api

jobs:
build_wheels:
name: Build API wheel/sdist
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ env.PACKAGE_DIR }}
steps:
- uses: actions/checkout@v3
with:
submodules: true

- uses: actions/setup-python@v4

- name: Build wheel
run: |
pip3 install build wheel
python3 -m build --wheel
env:
CIBW_ARCHS: ${{ matrix.archs }}
CIBW_SKIP: "*-musllinux_*"

- name: Build SDist
run: pipx run build --sdist

- uses: actions/upload-artifact@v3
with:
name: api-release
path: |
livekit-api/dist/*.whl
livekit-api/dist/*.tar.gz
publish:
name: Publish API release
needs: build_wheels
runs-on: ubuntu-latest
permissions:
id-token: write
if: startsWith(github.ref, 'refs/tags/api-v')
steps:
- uses: actions/download-artifact@v3
with:
name: api-release
path: dist

- uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__

Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
name: Build
name: Build RTC

on:
push:
branches: ["main"]
tags: ["v*"]
paths:
- livekit-rtc/**
pull_request:
paths:
- livekit-rtc/**
workflow_dispatch:

env:
PACKAGE_DIR: ./livekit-rtc

jobs:
build_wheels:
name: Build wheels (${{ matrix.archs }})
name: Build RTC wheels (${{ matrix.archs }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand All @@ -24,7 +29,9 @@ jobs:
archs: AMD64 # ignore windows arm64 for now
- os: macos-latest
archs: x86_64 arm64

defaults:
run:
working-directory: ${{ env.PACKAGE_DIR }}
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -39,16 +46,18 @@ jobs:
run: python3 -m cibuildwheel --output-dir dist
env:
CIBW_ARCHS: ${{ matrix.archs }}
CIBW_SKIP: "*-musllinux_*"

- uses: actions/upload-artifact@v3
with:
name: release
path: dist/*.whl
name: rtc-release
path: livekit-rtc/dist/*.whl

make_sdist:
name: Make SDist
name: Make RTC sdist
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ env.PACKAGE_DIR }}
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -59,21 +68,20 @@ jobs:

- uses: actions/upload-artifact@v3
with:
name: release
path: dist/*.tar.gz
name: rtc-release
path: livekit-rtc/dist/*.tar.gz

publish:
name: Publish
name: Publish RTC release
needs: [build_wheels, make_sdist]
runs-on: ubuntu-latest
permissions:
id-token: write
# only execute on tag push v1 or workflow_dispatch
if: (github.event_name == 'push' && github.ref_type == 'tag') || github.event_name == 'workflow_dispatch'
if: startsWith(github.ref, 'refs/tags/rtc-v')
steps:
- uses: actions/download-artifact@v3
with:
name: release
name: rtc-release
path: dist

- uses: pypa/gh-action-pypi-publish@release/v1
Expand Down
5 changes: 4 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "client-sdk-rust"]
path = rust-sdks
path = livekit-rtc/rust-sdks
url = https://github.com/livekit/rust-sdks
[submodule "livekit-api/protocol"]
path = livekit-api/protocol
url = https://github.com/livekit/protocol
68 changes: 34 additions & 34 deletions examples/basic_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,98 +3,98 @@
from signal import SIGINT, SIGTERM
from typing import Union

import livekit
from livekit import rtc

URL = 'ws://localhost:7880'
TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE5MDY2MTMyODgsImlzcyI6IkFQSVRzRWZpZFpqclFvWSIsIm5hbWUiOiJuYXRpdmUiLCJuYmYiOjE2NzI2MTMyODgsInN1YiI6Im5hdGl2ZSIsInZpZGVvIjp7InJvb20iOiJ0ZXN0Iiwicm9vbUFkbWluIjp0cnVlLCJyb29tQ3JlYXRlIjp0cnVlLCJyb29tSm9pbiI6dHJ1ZSwicm9vbUxpc3QiOnRydWV9fQ.uSNIangMRu8jZD5mnRYoCHjcsQWCrJXgHCs0aNIgBFY' # noqa


async def main(room: livekit.Room) -> None:
async def main(room: rtc.Room) -> None:

@room.listens_to("participant_connected")
def on_participant_connected(participant: livekit.RemoteParticipant) -> None:
def on_participant_connected(participant: rtc.RemoteParticipant) -> None:
logging.info(
"participant connected: %s %s", participant.sid, participant.identity)

@room.listens_to("participant_disconnected")
def on_participant_disconnected(participant: livekit.RemoteParticipant):
def on_participant_disconnected(participant: rtc.RemoteParticipant):
logging.info("participant disconnected: %s %s",
participant.sid, participant.identity)

@room.listens_to("local_track_published")
def on_local_track_published(publication: livekit.LocalTrackPublication,
track: Union[livekit.LocalAudioTrack,
livekit.LocalVideoTrack]):
def on_local_track_published(publication: rtc.LocalTrackPublication,
track: Union[rtc.LocalAudioTrack,
rtc.LocalVideoTrack]):
logging.info("local track published: %s", publication.sid)

@room.listens_to("active_speakers_changed")
def on_active_speakers_changed(speakers: list[livekit.Participant]):
def on_active_speakers_changed(speakers: list[rtc.Participant]):
logging.info("active speakers changed: %s", speakers)

@room.listens_to("local_track_unpublished")
def on_local_track_unpublished(publication: livekit.LocalTrackPublication):
def on_local_track_unpublished(publication: rtc.LocalTrackPublication):
logging.info("local track unpublished: %s", publication.sid)

@room.listens_to("track_published")
def on_track_published(publication: livekit.RemoteTrackPublication,
participant: livekit.RemoteParticipant):
def on_track_published(publication: rtc.RemoteTrackPublication,
participant: rtc.RemoteParticipant):
logging.info("track published: %s from participant %s (%s)",
publication.sid, participant.sid, participant.identity)

@room.listens_to("track_unpublished")
def on_track_unpublished(publication: livekit.RemoteTrackPublication,
participant: livekit.RemoteParticipant):
def on_track_unpublished(publication: rtc.RemoteTrackPublication,
participant: rtc.RemoteParticipant):
logging.info("track unpublished: %s", publication.sid)

@room.listens_to("track_subscribed")
def on_track_subscribed(track: livekit.Track,
publication: livekit.RemoteTrackPublication,
participant: livekit.RemoteParticipant):
def on_track_subscribed(track: rtc.Track,
publication: rtc.RemoteTrackPublication,
participant: rtc.RemoteParticipant):
logging.info("track subscribed: %s", publication.sid)
if track.kind == livekit.TrackKind.KIND_VIDEO:
_video_stream = livekit.VideoStream(track)
if track.kind == rtc.TrackKind.KIND_VIDEO:
_video_stream = rtc.VideoStream(track)
# video_stream is an async iterator that yields VideoFrame
elif track.kind == livekit.TrackKind.KIND_AUDIO:
elif track.kind == rtc.TrackKind.KIND_AUDIO:
print("Subscribed to an Audio Track")
_audio_stream = livekit.AudioStream(track)
_audio_stream = rtc.AudioStream(track)
# audio_stream is an async iterator that yields AudioFrame

@room.listens_to("track_unsubscribed")
def on_track_unsubscribed(track: livekit.Track,
publication: livekit.RemoteTrackPublication,
participant: livekit.RemoteParticipant):
def on_track_unsubscribed(track: rtc.Track,
publication: rtc.RemoteTrackPublication,
participant: rtc.RemoteParticipant):
logging.info("track unsubscribed: %s", publication.sid)

@room.listens_to("track_muted")
def on_track_muted(publication: livekit.RemoteTrackPublication,
participant: livekit.RemoteParticipant):
def on_track_muted(publication: rtc.RemoteTrackPublication,
participant: rtc.RemoteParticipant):
logging.info("track muted: %s", publication.sid)

@room.listens_to("track_unmuted")
def on_track_unmuted(publication: livekit.RemoteTrackPublication,
participant: livekit.RemoteParticipant):
def on_track_unmuted(publication: rtc.RemoteTrackPublication,
participant: rtc.RemoteParticipant):
logging.info("track unmuted: %s", publication.sid)

@room.listens_to("data_received")
def on_data_received(data: bytes,
kind: livekit.DataPacketKind,
participant: livekit.Participant):
kind: rtc.DataPacketKind,
participant: rtc.Participant):
logging.info("received data from %s: %s", participant.identity, data)

@room.listens_to("connection_quality_changed")
def on_connection_quality_changed(participant: livekit.Participant,
quality: livekit.ConnectionQuality):
def on_connection_quality_changed(participant: rtc.Participant,
quality: rtc.ConnectionQuality):
logging.info("connection quality changed for %s", participant.identity)

@room.listens_to("track_subscription_failed")
def on_track_subscription_failed(participant: livekit.RemoteParticipant,
def on_track_subscription_failed(participant: rtc.RemoteParticipant,
track_sid: str,
error: str):
logging.info("track subscription failed: %s %s",
participant.identity, error)

@room.listens_to("connection_state_changed")
def on_connection_state_changed(state: livekit.ConnectionState):
def on_connection_state_changed(state: rtc.ConnectionState):
logging.info("connection state changed: %s", state)

@room.listens_to("connected")
Expand Down Expand Up @@ -127,7 +127,7 @@ def on_reconnected() -> None:
logging.StreamHandler()])

loop = asyncio.get_event_loop()
room = livekit.Room(loop=loop)
room = rtc.Room(loop=loop)

async def cleanup():
await room.disconnect()
Expand Down
35 changes: 17 additions & 18 deletions examples/e2ee.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,24 @@
from signal import SIGINT, SIGTERM

import numpy as np

import livekit
from livekit import rtc

URL = 'ws://localhost:7880'
TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE5MDY2MTMyODgsImlzcyI6IkFQSVRzRWZpZFpqclFvWSIsIm5hbWUiOiJuYXRpdmUiLCJuYmYiOjE2NzI2MTMyODgsInN1YiI6Im5hdGl2ZSIsInZpZGVvIjp7InJvb20iOiJ0ZXN0Iiwicm9vbUFkbWluIjp0cnVlLCJyb29tQ3JlYXRlIjp0cnVlLCJyb29tSm9pbiI6dHJ1ZSwicm9vbUxpc3QiOnRydWV9fQ.uSNIangMRu8jZD5mnRYoCHjcsQWCrJXgHCs0aNIgBFY' # noqa

# ("livekitrocks") this is our shared key, it must match the one used by your clients
SHARED_KEY = b"livekitrocks"
SHARED_KEY = b"liveitrocks"


async def draw_cube(source: livekit.VideoSource):
async def draw_cube(source: rtc.VideoSource):
W, H, MID_W, MID_H = 1280, 720, 640, 360
cube_size = 60
vertices = (np.array([[-1, -1, -1], [1, -1, -1], [1, 1, -1], [-1, 1, -1],
[-1, -1, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1]]) * cube_size)
edges = [[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6],
[6, 7], [7, 4], [0, 4], [1, 5], [2, 6], [3, 7]]

frame = livekit.ArgbFrame(livekit.VideoFormatType.FORMAT_ARGB, W, H)
frame = rtc.ArgbFrame(livekit.VideoFormatType.FORMAT_ARGB, W, H)
arr = np.ctypeslib.as_array(frame.data)
angle = 0

Expand All @@ -48,41 +47,41 @@ async def draw_cube(source: livekit.VideoSource):
idx = (y + dy) * W * 4 + (x + dx) * 4
arr[idx:idx+4] = [255, 255, 255, 255]

f = livekit.VideoFrame(
0, livekit.VideoRotation.VIDEO_ROTATION_0, frame.to_i420())
f = rtc.VideoFrame(
0, rtc.VideoRotation.VIDEO_ROTATION_0, frame.to_i420())
source.capture_frame(f)
angle += 0.02

code_duration = asyncio.get_event_loop().time() - start_time
await asyncio.sleep(1 / 30 - code_duration)


async def main(room: livekit.Room):
async def main(room: rtc.Room):
@room.listens_to("e2ee_state_changed")
def on_e2ee_state_changed(participant: livekit.Participant,
state: livekit.EncryptionState) -> None:
def on_e2ee_state_changed(participant: rtc.Participant,
state: rtc.EncryptionState) -> None:
logging.info("e2ee state changed: %s %s", participant.identity, state)

logging.info("connecting to %s", URL)
try:
e2ee_options = livekit.E2EEOptions()
e2ee_options = rtc.E2EEOptions()
e2ee_options.key_provider_options.shared_key = SHARED_KEY

await room.connect(URL, TOKEN, options=livekit.RoomOptions(
await room.connect(URL, TOKEN, options=rtc.RoomOptions(
auto_subscribe=True,
e2ee=e2ee_options
))

logging.info("connected to room %s", room.name)
except livekit.ConnectError as e:
except rtc.ConnectError as e:
logging.error("failed to connect to the room: %s", e)
return False

# publish a track
source = livekit.VideoSource()
track = livekit.LocalVideoTrack.create_video_track("cube", source)
options = livekit.TrackPublishOptions()
options.source = livekit.TrackSource.SOURCE_CAMERA
source = rtc.VideoSource()
track = rtc.LocalVideoTrack.create_video_track("cube", source)
options = rtc.TrackPublishOptions()
options.source = rtc.TrackSource.SOURCE_CAMERA
publication = await room.local_participant.publish_track(track, options)
logging.info("published track %s", publication.sid)

Expand All @@ -94,7 +93,7 @@ def on_e2ee_state_changed(participant: livekit.Participant,
logging.StreamHandler()])

loop = asyncio.get_event_loop()
room = livekit.Room(loop=loop)
room = rtc.Room(loop=loop)

async def cleanup():
await room.disconnect()
Expand Down
Loading

0 comments on commit 907be69

Please sign in to comment.