steep-balloon-41261
11/20/2023, 5:12 PMloud-jewelry-13301
11/20/2023, 5:50 PMadventurous-twilight-28575
11/20/2023, 6:28 PMadventurous-twilight-28575
11/20/2023, 7:10 PMloud-jewelry-13301
11/20/2023, 9:28 PMacoustic-engineer-41666
11/20/2023, 10:28 PMacoustic-engineer-41666
11/20/2023, 10:28 PMdry-elephant-14928
11/21/2023, 4:11 AMadventurous-twilight-28575
11/21/2023, 8:27 AMadventurous-twilight-28575
11/21/2023, 8:33 AMdry-elephant-14928
11/22/2023, 2:49 AMadventurous-twilight-28575
11/22/2023, 6:19 AMadventurous-twilight-28575
11/22/2023, 8:34 AMadventurous-twilight-28575
11/23/2023, 8:37 AMv4l2src device=/dev/video0 for avfvideosrc and avenc_h264 for avenc_h264_videotoolbox)
Then there is a typo in the a.m. demo: The H.264 URL has one slash too much, livekit-cli complains. Then I had to change 127.0.0.1 to localhost. Unknown reason, but the connection was refused with 127.0.0.1. Maybe it was attempted via IPv6, that's why. I didn't investigate.
Also somehow important the selection of capture resolution and encoding bitrate. Otherwise it was capturing in 1521 x 1521 or so over here and encoding with about 300 kBps -> terrible quality
Here is the gist:
- Fire up a live-kit dev server in one terminal window: livekit-server --dev
- Fire up the GStreamer pipeline in another terminal window: gst-launch-1.0 avfvideosrc device-index=0 ! video/x-raw, width=1920, height=1080, framerate=30/1 ! avenc_h264_videotoolbox bitrate=5000000 ! tcpserversink port=16400
- Fire up the publisher in a third window: livekit-cli join-room --url <ws://localhost:7880> --api-key devkey --api-secret secret --room abcde --identity bot --publish <h264://localhost:16400>
- Now you would need a subscriber. I was using an index.html with the content below and "organized" a token by livekit-cli create-token --api-key devkey --api-secret secret --join --room abcde --identity Neil --valid-for 160h.
- So a fourth terminal window is now hosting the index.html by using live-server, installed globally with Node and NPM. index.html is available at localhost:8080 in your browser then.
Results were pretty nice, full HD in decent qualtity and latency. Chrome's WebRTC-Internals confirmed to have H.264 at the configured bitrate of 5 MBit/s in full HD at 30 fps. Not bad, not bad :)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Livekit Example</title>
</head>
<body>
<div id="video-container">
</div>
<script src="<https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.js>"></script>
<script>
const url= "<ws://localhost:7880>"
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MDEzMDQxMDUsImlzcyI6ImRldmtleSIsIm5hbWUiOiJOZWlsIiwibmJmIjoxNzAwNzI4MTA1LCJzdWIiOiJOZWlsIiwidmlkZW8iOnsicm9vbSI6ImFiY2RlIiwicm9vbUpvaW4iOnRydWV9fQ.gGnm0ifnrLRSzX69YFV-3acqjDuwpRYmRIUISEA3LjM"
debugger
// creates a new room with options
const room = new LivekitClient.Room()
// pre-warm connection, this can be called as early as your page is loaded
room.prepareConnection(url, token)
// set up event listeners
room
.on(LivekitClient.RoomEvent.TrackSubscribed, handleTrackSubscribed)
.on(LivekitClient.RoomEvent.TrackUnsubscribed, handleTrackUnsubscribed)
.on(LivekitClient.RoomEvent.ActiveSpeakersChanged, handleActiveSpeakerChange)
.on(LivekitClient.RoomEvent.Disconnected, handleDisconnect)
.on(LivekitClient.RoomEvent.LocalTrackUnpublished, handleLocalTrackUnpublished);
function handleTrackSubscribed(track, publication, participant) {
if (track.kind === "video") {
// attach it to a new HTMLVideoElement or HTMLAudioElement
const videoElement = document.getElementById('video-container');
const element = track.attach();
videoElement.appendChild(element);
}
}
function handleTrackUnsubscribed(track, publication, participant) {
// remove tracks from all attached elements
track.detach();
}
function handleLocalTrackUnpublished(publication, participant) {
// when local tracks are ended, update UI to remove them from rendering
publication.track.detach();
}
function handleActiveSpeakerChange(speakers) {
// show UI indicators when participant is speaking
}
function handleDisconnect() {
console.log('disconnected from room');
}
async function subscribeToRoom(token, url) {
await room.connect(url, token)
console.log('connected to room', room.name);
}
subscribeToRoom(token, url);
</script>
</body>
</html>adventurous-twilight-28575
11/23/2023, 9:03 AMvp8 source fails:
`gst-launch-1.0 avfvideosrc device-index=0 ! video/x-raw, width=1280, height=720, framerate=30/1 ! videoconvert ! vp8enc deadline=1 ! tcpserversink port=16400``
Publishing like so:
livekit-cli join-room --url <ws://localhost:7880> --api-key devkey --api-secret secret --room abcde --identity bot --publish <vp8://localhost:16400>
It starts but fires an error quickly:
2023/11/23 10:00:50 "msg"="Could not start writing" "error"="IVF signature mismatch"adventurous-twilight-28575
11/23/2023, 9:58 AMadventurous-twilight-28575
11/23/2023, 8:42 PMlivekit-cli after having started the pipeline (see https://github.com/livekit/livekit-cli/issues/251)adventurous-twilight-28575
11/23/2023, 8:46 PMlivekit-cli join-room --url <ws://localhost:7880> --api-key devkey --api-secret secret --room abcde --identity bot --publish <h264://tmp/myvideo.sock>
The python app provides a UnixSocks server and starts the GStreamer pipeline then. The results are perfect, but - here we go again: No simulcast. Thinking twice I believe there must be a mistake somewhere. I can't really imagine where - with the provision of only one H.264 stream - simulcast is supposed to come from... But how can I make several encoded streams available with the resources I have? I think I need to take another look at the demo example. What exactly happens there? Basically, I can only imagine that 3 streams with different spatial layers are generated simultaneously from some endless raw loop and these are then - depending on the bandwidth - made available to the consumer...