const { MediaStreamTrack, randomPort, RTCPeerConnection, RTCRtpCodecParameters, RtpPacket } = require('werift') const { Server } = require('ws') const { createSocket } = require('dgram') const { exec } = require('child_process') // open answer.html const server = new Server({ port: 8888 }); console.log("start"); server.on("connection", async (socket) => { console.log('客户端连接'); const payloadType = 96; const pc = new RTCPeerConnection({ codecs: { audio: [], video: [ new RTCRtpCodecParameters({ mimeType: "video/h264", clockRate: 90000, payloadType: payloadType, }), ], }, iceServers: [ // { // urls: [ // "stun:caner.top:3478", // "stun:stun.l.google.com:19302", // "stun:stun1.l.google.com:19302", // "stun:stun2.l.google.com:19302", // "stun:stun3.l.google.com:19302", // ], // }, // { // urls: "turn:caner.top:3478", // username: "admin", // credential: "123456", // }, ] }); const track = new MediaStreamTrack({ kind: "video" }) randomPort().then((port) => { const udp = createSocket("udp4"); udp.bind(port); console.log('端口',port); // test vp8 /** * -lavfi 定义一个复杂的过滤器图 */ // exec(`D:/ffmpeg-4.4-full_build/bin/ffmpeg.exe -re -f lavfi -i testsrc=size=640x480:rate=30 -vcodec libvpx -cpu-used 5 -deadline 1 -g 10 -error-resilient 1 -auto-alt-ref 1 -f rtp rtp://127.0.0.1:${port}`,(error, stdout, stderr) => { // if (error) { // console.error(`exec error: ${error}`); // return; // } // console.log(`stdout: ${stdout}`); // console.error(`stderr: ${stderr}`); // }) // win video h264 /** * -re 以原生帧速率读取输入 * -f 强制格式 * dshow 直接捕获视频 * -s 视频大小 * -discard 在输入之前丢弃帧(noref:丢弃非参考帧,bidir:丢弃双向帧,nokey:丢弃非关键帧) * -xerror 出错时停止并退出 * -i 输入 * -pix_fmt 视频格式 * -c 在输入之后是编码,在输入之前是解码 * -vstats 视频日志 * rtp 输出格式 */ exec(`D:/ffmpeg-4.4-full_build/bin/ffmpeg.exe -re -f dshow -s 640x480 -discard nokey -xerror -i video="Logitech HD Webcam C525" -pix_fmt yuv420p -c h264 -vstats -cpu-used 10 -g 5 -preset ultrafast -tune zerolatency -f rtp rtp://127.0.0.1:${port}`, (error, stdout, stderr) => { if (error) { console.error(`exec error: ${error}`); return; } }) udp.on("message", (data) => { const rtp = RtpPacket.deSerialize(data); rtp.header.payloadType = payloadType; track.writeRtp(rtp); }); }); pc.addTransceiver(track, { direction: "sendonly" }); await pc.setLocalDescription(await pc.createOffer()); const sdp = JSON.stringify(pc.localDescription); socket.send(sdp); socket.on("message", (data) => { pc.setRemoteDescription(JSON.parse(data)); }); });