1
1
import asyncio
2
- import colorsys
3
2
import logging
4
3
from signal import SIGINT , SIGTERM
5
4
10
9
URL = 'ws://localhost:7880'
11
10
TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE5MDY2MTMyODgsImlzcyI6IkFQSVRzRWZpZFpqclFvWSIsIm5hbWUiOiJuYXRpdmUiLCJuYmYiOjE2NzI2MTMyODgsInN1YiI6Im5hdGl2ZSIsInZpZGVvIjp7InJvb20iOiJ0ZXN0Iiwicm9vbUFkbWluIjp0cnVlLCJyb29tQ3JlYXRlIjp0cnVlLCJyb29tSm9pbiI6dHJ1ZSwicm9vbUxpc3QiOnRydWV9fQ.uSNIangMRu8jZD5mnRYoCHjcsQWCrJXgHCs0aNIgBFY' # noqa
12
11
12
+ # ("livekitrocks") this is our shared key, it must match the one used by your clients
13
+ SHARED_KEY = b"livekitrocks"
13
14
14
- async def publish_frames (source : livekit .VideoSource ):
15
- argb_frame = livekit .ArgbFrame (
16
- livekit .VideoFormatType .FORMAT_ARGB , 1280 , 720 )
17
15
18
- arr = np .ctypeslib .as_array (argb_frame .data )
16
+ async def draw_cube (source : livekit .VideoSource ):
17
+ W , H , MID_W , MID_H = 1280 , 720 , 640 , 360
18
+ cube_size = 60
19
+ vertices = (np .array ([[- 1 , - 1 , - 1 ], [1 , - 1 , - 1 ], [1 , 1 , - 1 ], [- 1 , 1 , - 1 ],
20
+ [- 1 , - 1 , 1 ], [1 , - 1 , 1 ], [1 , 1 , 1 ], [- 1 , 1 , 1 ]]) * cube_size )
21
+ edges = [[0 , 1 ], [1 , 2 ], [2 , 3 ], [3 , 0 ], [4 , 5 ], [5 , 6 ],
22
+ [6 , 7 ], [7 , 4 ], [0 , 4 ], [1 , 5 ], [2 , 6 ], [3 , 7 ]]
19
23
20
- framerate = 1 / 30
21
- hue = 0.0
24
+ frame = livekit .ArgbFrame (livekit .VideoFormatType .FORMAT_ARGB , W , H )
25
+ arr = np .ctypeslib .as_array (frame .data )
26
+ angle = 0
22
27
23
28
while True :
24
- frame = livekit .VideoFrame (
25
- 0 , livekit .VideoRotation .VIDEO_ROTATION_0 , argb_frame .to_i420 ())
26
-
27
- rgb = colorsys .hsv_to_rgb (hue , 1.0 , 1.0 )
28
- rgb = [(x * 255 ) for x in rgb ] # type: ignore
29
-
30
- argb_color = np .array (rgb + [255 ], dtype = np .uint8 )
31
- arr .flat [::4 ] = argb_color [0 ]
32
- arr .flat [1 ::4 ] = argb_color [1 ]
33
- arr .flat [2 ::4 ] = argb_color [2 ]
34
- arr .flat [3 ::4 ] = argb_color [3 ]
35
-
36
- source .capture_frame (frame )
37
-
38
- hue += framerate / 3 # 3s for a full cycle
39
- if hue >= 1.0 :
40
- hue = 0.0
41
-
42
- try :
43
- await asyncio .sleep (framerate )
44
- except asyncio .CancelledError :
45
- break
46
-
47
-
48
- async def main ():
49
- room = livekit .Room ()
50
-
29
+ start_time = asyncio .get_event_loop ().time ()
30
+ arr .fill (0 )
31
+ rot = np .dot (np .array ([[1 , 0 , 0 ],
32
+ [0 , np .cos (angle ), - np .sin (angle )],
33
+ [0 , np .sin (angle ), np .cos (angle )]]),
34
+ np .array ([[np .cos (angle ), 0 , np .sin (angle )],
35
+ [0 , 1 , 0 ],
36
+ [- np .sin (angle ), 0 , np .cos (angle )]]))
37
+ proj_points = [[int (pt [0 ] / (pt [2 ] / 200 + 1 )), int (pt [1 ] / (pt [2 ] / 200 + 1 ))]
38
+ for pt in np .dot (vertices , rot )]
39
+
40
+ for e in edges :
41
+ x1 , y1 , x2 , y2 = * proj_points [e [0 ]], * proj_points [e [1 ]]
42
+ for t in np .linspace (0 , 1 , 100 ):
43
+ x , y = int (MID_W + (1 - t ) * x1 + t *
44
+ x2 ), int (MID_H + (1 - t ) * y1 + t * y2 )
45
+ for dx in [- 1 , 0 , 1 ]:
46
+ for dy in [- 1 , 0 , 1 ]:
47
+ if 0 <= x + dx < W and 0 <= y + dy < H :
48
+ idx = (y + dy ) * W * 4 + (x + dx ) * 4
49
+ arr [idx :idx + 4 ] = [255 , 255 , 255 , 255 ]
50
+
51
+ f = livekit .VideoFrame (
52
+ 0 , livekit .VideoRotation .VIDEO_ROTATION_0 , frame .to_i420 ())
53
+ source .capture_frame (f )
54
+ angle += 0.02
55
+
56
+ code_duration = asyncio .get_event_loop ().time () - start_time
57
+ await asyncio .sleep (1 / 30 - code_duration )
58
+
59
+
60
+ async def main (room : livekit .Room ):
51
61
@room .listens_to ("e2ee_state_changed" )
52
62
def on_e2ee_state_changed (participant : livekit .Participant ,
53
63
state : livekit .EncryptionState ) -> None :
@@ -56,7 +66,7 @@ def on_e2ee_state_changed(participant: livekit.Participant,
56
66
logging .info ("connecting to %s" , URL )
57
67
try :
58
68
e2ee_options = livekit .E2EEOptions ()
59
- e2ee_options .key_provider_options .shared_key = b"livekitrocks" # this is our e2ee key
69
+ e2ee_options .key_provider_options .shared_key = SHARED_KEY
60
70
61
71
await room .connect (URL , TOKEN , options = livekit .RoomOptions (
62
72
auto_subscribe = True ,
@@ -68,33 +78,34 @@ def on_e2ee_state_changed(participant: livekit.Participant,
68
78
logging .error ("failed to connect to the room: %s" , e )
69
79
return False
70
80
81
+ # publish a track
71
82
source = livekit .VideoSource ()
72
- source_task = asyncio .create_task (publish_frames (source ))
73
-
74
- track = livekit .LocalVideoTrack .create_video_track ("hue" , source )
83
+ track = livekit .LocalVideoTrack .create_video_track ("cube" , source )
75
84
options = livekit .TrackPublishOptions ()
76
85
options .source = livekit .TrackSource .SOURCE_CAMERA
77
86
publication = await room .local_participant .publish_track (track , options )
78
87
logging .info ("published track %s" , publication .sid )
79
88
80
- try :
81
- await room .run ()
82
- except asyncio .CancelledError :
83
- logging .info ("closing the room" )
84
- source_task .cancel ()
85
- await source_task
86
- await room .disconnect ()
87
-
89
+ asyncio .ensure_future (draw_cube (source ))
88
90
89
91
if __name__ == "__main__" :
90
92
logging .basicConfig (level = logging .INFO , handlers = [
91
- logging .FileHandler ("publish_hue.log" ), logging .StreamHandler ()])
93
+ logging .FileHandler ("e2ee.log" ),
94
+ logging .StreamHandler ()])
92
95
93
96
loop = asyncio .get_event_loop ()
94
- main_task = asyncio .ensure_future (main ())
97
+ room = livekit .Room (loop = loop )
98
+
99
+ async def cleanup ():
100
+ await room .disconnect ()
101
+ loop .stop ()
102
+
103
+ asyncio .ensure_future (main (room ))
95
104
for signal in [SIGINT , SIGTERM ]:
96
- loop .add_signal_handler (signal , main_task .cancel )
105
+ loop .add_signal_handler (
106
+ signal , lambda : asyncio .ensure_future (cleanup ()))
107
+
97
108
try :
98
- loop .run_until_complete ( main_task )
109
+ loop .run_forever ( )
99
110
finally :
100
111
loop .close ()
0 commit comments