Anonymous
Как улучшить задержку потоковой передачи веб -камеры до устройства v4l2loopback с FFMPEG?
Сообщение
Anonymous » 09 мар 2025, 23:41
Я пытаюсь транслировать свою камеру iPhone на свой компьютер на локальной локальной локальной локальной локальной локальной локальной локальной сети. /> < /li>
< /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
~ 150 мс на самом деле слишком много для 15 КБ на локальной сети, но у моего маршрутизатора может возникнуть некоторые проблемы
[*] Насколько я не могу сказать, что не связано с пропускной способностью 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
[*] Я также попытался написать видеопоток непосредственно в файл video.mp4 и немедленно открыть его с помощью vlc , но его можно успешно открыть только после ~ 1,5 с. То же самое
[/list]
Подробнее здесь:
https://stackoverflow.com/questions/794 ... ith-ffmpeg
1741552896
Anonymous
Я пытаюсь транслировать свою камеру iPhone на свой компьютер на локальной локальной локальной локальной локальной локальной локальной локальной сети. /> < /li> < /ol> [code]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 [/code] ~ 150 мс на самом деле слишком много для 15 КБ на локальной сети, но у моего маршрутизатора может возникнуть некоторые проблемы [*] Насколько я не могу сказать, что не связано с пропускной способностью ffmpeg: [code]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 [/code] [*] Я также попытался написать видеопоток непосредственно в файл video.mp4 и немедленно открыть его с помощью vlc , но его можно успешно открыть только после ~ 1,5 с. То же самое [/list] Подробнее здесь: [url]https://stackoverflow.com/questions/79496570/how-to-improve-web-camera-streaming-latency-to-v4l2loopback-device-with-ffmpeg[/url]