< /ol>
Код: Выделить всё
async function beginCameraStream() {
const mediaStream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: "user" },
});
websocket = new WebSocket(SERVER_URL);
websocket.onopen = () => {
console.log("WS connected");
const options = { mimeType: "video/mp4", videoBitsPerSecond: 1_000_000 };
mediaRecorder = new MediaRecorder(mediaStream, options);
mediaRecorder.ondataavailable = async (event) => {
// to measure latency I prepend timestamp to the actual video bytes chunk
const timestamp = Date.now();
const timestampBuffer = new ArrayBuffer(8);
const dataView = new DataView(timestampBuffer);
dataView.setBigUint64(0, BigInt(timestamp), true);
const data = await event.data.bytes();
const result = new Uint8Array(data.byteLength + 8);
result.set(new Uint8Array(timestampBuffer), 0);
result.set(data, 8);
websocket.send(result);
};
mediaRecorder.start(100); // Collect 100ms chunks
};
}
< /code>
[*] сервер для обработки видеофолков < /h3>
< /li>
< /ol>
import { serve } from "bun";
import { Readable } from "stream";
const V4L2LOOPBACK_DEVICE = "/dev/video10";
export const setupFFmpeg = (v4l2device) => {
// prettier-ignore
return spawn("ffmpeg", [
'-i', 'pipe:0', // Read from stdin
'-pix_fmt', 'yuv420p', // Pixel format
'-r', '30', // Target 30 fps
'-f', 'v4l2', // Output format
v4l2device, // Output to v4l2loopback device
]);
};
export class FfmpegStream extends Readable {
_read() {
// This is called when the stream wants more data
// We push data when we get chunks
}
}
function main() {
const ffmpeg = setupFFmpeg(V4L2LOOPBACK_DEVICE);
serve({
port: 8000,
fetch(req, server) {
if (server.upgrade(req)) {
return; // Upgraded to WebSocket
}
},
websocket: {
open(ws) {
console.log("Client connected");
const stream = new FfmpegStream();
stream.pipe(ffmpeg?.stdin);
ws.data = {
stream,
received: 0,
};
},
async message(ws, message) {
const view = new DataView(message.buffer, 0, 8);
const ts = Number(view.getBigUint64(0, true));
ws.data.received += message.byteLength;
const chunk = new Uint8Array(message.buffer, 8, message.byteLength - 8);
ws.data.stream.push(chunk);
console.log(
[
`latency: ${Date.now() - ts} ms`,
`chunk: ${message.byteLength}`,
`total: ${ws.data.received}`,
].join(" | "),
);
},
},
});
}
main();
< /code>
после того, как я попытаюсь открыть устройство v4l2loopback < /p>
cvlc v4l2:///dev/video10
< /code>
изображение откладывается, по крайней мере, для 1,5 < /strong> Sec, что неприемлемо для моего проекта. < /p>
Мысли: < /h3>
[list]
Проблема не связана с сетевой латентностью < /p>
.latency: 140 ms | chunk: 661 Bytes | total: 661 Bytes
latency: 206 ms | chunk: 16.76 KB | total: 17.41 KB
latency: 141 ms | chunk: 11.28 KB | total: 28.68 KB
latency: 141 ms | chunk: 13.05 KB | total: 41.74 KB
latency: 199 ms | chunk: 11.39 KB | total: 53.13 KB
latency: 141 ms | chunk: 16.94 KB | total: 70.07 KB
latency: 139 ms | chunk: 12.67 KB | total: 82.74 KB
latency: 142 ms | chunk: 13.14 KB | total: 95.88 KB
[*] Насколько я не могу сказать, что не связано с пропускной способностью ffmpeg:
Код: Выделить всё
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'pipe:0':
Metadata:
major_brand : iso5
minor_version : 1
compatible_brands: isomiso5hlsf
creation_time : 2025-03-09T17:16:49.000000Z
Duration: 00:00:01.38, start:
0.000000, bitrate: N/A
Stream #0:0(und): Video: h264 (Baseline) (avc1 / 0x31637661), yuvj420p(pc), 1280x720, 4012 kb/s, 57.14 fps, 29.83 tbr, 600 tbn, 1200 tbc (default)
Metadata:
rotate : 90
creation_time : 2025-03-09T17:16:49.000000Z
handler_name : Core Media Video
Side data:
displaymatrix: rotation of -90.00 degrees
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> rawvideo (native))
[swscaler @ 0x55d8d0b83100] deprecated pixel format used, make sure you did set range correctly
Output #0, video4linux2,v4l2, to '/dev/video10':
Metadata:
major_brand : iso5
minor_version : 1
compatible_brands: isomiso5hlsf
encoder : Lavf58.45.100
Stream #0:0(und): Video: rawvideo (I420 / 0x30323449), yuv420p, 720x1280, q=2-31, 663552 kb/s, 60 fps, 60 tbn, 60 tbc (default)
Metadata:
encoder : Lavc58.91.100 rawvideo
creation_time : 2025-03-09T17:16:49.000000Z
handler_name : Core Media Video
Side data:
displaymatrix: rotation of -0.00 degrees
frame= 99 fps=0.0 q=-0.0 size=N/A time=00:00:01.65 bitrate=N/A dup=50 drop=0 speed=2.77x
frame= 137 fps=114 q=-0.0 size=N/A time=00:00:02.28 bitrate=N/A dup=69 drop=0 speed=1.89x
frame= 173 fps= 98 q=-0.0 size=N/A time=00:00:02.88 bitrate=N/A dup=87 drop=0 speed=1.63x
frame= 210 fps= 86 q=-0.0 size=N/A time=00:00:03.50 bitrate=N/A dup=105 drop=0 speed=1.44x
frame= 249 fps= 81 q=-0.0 size=N/A time=00:00:04.15 bitrate=N/A dup=125 drop=0 speed=1.36
frame= 279 fps= 78 q=-0.0 size=N/A time=00:00:04.65 bitrate=N/A dup=139 drop=0 speed=1.31x
[/list]
Подробнее здесь: https://stackoverflow.com/questions/794 ... ith-ffmpeg