initial commit
This commit is contained in:
130
test_livekit.py
Normal file
130
test_livekit.py
Normal file
@ -0,0 +1,130 @@
|
||||
import asyncio
|
||||
import requests
|
||||
from livekit import rtc
|
||||
|
||||
import wave
|
||||
import numpy as np
|
||||
from livekit.rtc import AudioSource, AudioFrame, LocalAudioTrack
|
||||
|
||||
TOKEN_URL = "http://localhost:8000/getToken"
|
||||
WS_URL = "wss://esp32-vt80c4y6.livekit.cloud" # 你的 LiveKit Server 地址
|
||||
|
||||
ROOM_NAME = "test-room20"
|
||||
import uuid
|
||||
IDENTITY = f"uv-{uuid.uuid4().hex[:6]}"
|
||||
# IDENTITY = "test-user0"
|
||||
|
||||
|
||||
def get_token():
|
||||
resp = requests.get(
|
||||
TOKEN_URL,
|
||||
params={
|
||||
"room": ROOM_NAME,
|
||||
"identity": IDENTITY,
|
||||
"agent_name": "my-agent", # 关键!!!
|
||||
},
|
||||
)
|
||||
data = resp.json()
|
||||
return data["token"]
|
||||
|
||||
|
||||
async def main():
|
||||
token = get_token()
|
||||
|
||||
room = rtc.Room()
|
||||
|
||||
@room.on("participant_connected")
|
||||
def on_participant_connected(participant):
|
||||
print(f"✅ 有人加入房间: {participant.identity}")
|
||||
|
||||
@room.on("participant_disconnected")
|
||||
def on_participant_disconnected(participant):
|
||||
print(f"❌ 有人离开房间: {participant.identity}")
|
||||
|
||||
print("🔌 正在连接房间...")
|
||||
await room.connect(WS_URL, token)
|
||||
|
||||
print("✅ 已连接房间:", ROOM_NAME)
|
||||
print("当前房间成员:")
|
||||
for p in room.remote_participants.values():
|
||||
print(" -", p.identity)
|
||||
|
||||
@room.on("data_received")
|
||||
def on_data_received(data, participant, kind, topic):
|
||||
try:
|
||||
msg = data.decode()
|
||||
print(f"📩 来自 {participant.identity}: {msg}")
|
||||
except:
|
||||
print("📩 收到二进制数据")
|
||||
|
||||
@room.on("track_subscribed")
|
||||
def on_track_subscribed(track, publication, participant):
|
||||
print(f"🎧 订阅轨道: {participant.identity}")
|
||||
|
||||
if track.kind == rtc.TrackKind.KIND_AUDIO:
|
||||
print("👉 TTS 音频来了")
|
||||
|
||||
# 等一下确保连接稳定
|
||||
await asyncio.sleep(1)
|
||||
await room.local_participant.publish_data(
|
||||
b"hello",
|
||||
reliable=True,
|
||||
topic="chat"
|
||||
)
|
||||
# 上传 wav
|
||||
await publish_wav(room, "2food.wav")
|
||||
|
||||
await room.disconnect()
|
||||
|
||||
|
||||
async def publish_wav(room, wav_path):
|
||||
print("🎵 开始上传本地 wav:", wav_path)
|
||||
|
||||
wf = wave.open(wav_path, "rb")
|
||||
|
||||
sample_rate = wf.getframerate()
|
||||
num_channels = wf.getnchannels()
|
||||
sample_width = wf.getsampwidth()
|
||||
|
||||
print(f"📊 WAV信息: {sample_rate}Hz, {num_channels}ch, {sample_width*8}bit")
|
||||
|
||||
# 创建音频源
|
||||
source = AudioSource(sample_rate, num_channels)
|
||||
|
||||
# 创建本地音轨
|
||||
track = LocalAudioTrack.create_audio_track("mic", source)
|
||||
|
||||
# 发布轨道
|
||||
await room.local_participant.publish_track(track)
|
||||
print("📡 已发布音轨")
|
||||
|
||||
frame_duration = 0.02 # 20ms
|
||||
samples_per_frame = int(sample_rate * frame_duration)
|
||||
|
||||
while True:
|
||||
data = wf.readframes(samples_per_frame)
|
||||
if not data:
|
||||
break
|
||||
|
||||
# 用于计算长度
|
||||
audio = np.frombuffer(data, dtype=np.int16)
|
||||
|
||||
if len(audio) == 0:
|
||||
continue
|
||||
|
||||
samples_per_channel = len(audio) // num_channels
|
||||
|
||||
frame = AudioFrame(
|
||||
data=data, # ✅ 关键:用 bytes
|
||||
sample_rate=sample_rate,
|
||||
num_channels=num_channels,
|
||||
samples_per_channel=samples_per_channel,
|
||||
)
|
||||
|
||||
await source.capture_frame(frame)
|
||||
await asyncio.sleep(frame_duration)
|
||||
print("✅ wav 推流结束")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user