如何在不重新加载页面的情况下播放视频流?

问题描述 投票:0回答:1

我创建了一个 Node js 服务器来 1)接收 udp 中的图像并将其转换为视频和 2)在网站上显示它

  1. 我尝试过,但我不明白如何在不重新加载页面的情况下直播视频

node js 服务器代码:

const express = require('express');
const dgram = require('dgram');
const fs = require('fs');
const ffmpeg = require('fluent-ffmpeg');
const path = require('path');
const WebSocket = require('ws');

const app = express();
const httpPort = 3000;

const imageDir = path.join(__dirname, 'images');
if (!fs.existsSync(imageDir)) {
    fs.mkdirSync(imageDir);
}

let imageCount = 0;

const udpPort = 15002;
const udpHost = '127.0.0.1';
const server = dgram.createSocket('udp4');

const wss = new WebSocket.Server({ noServer: true });


const createVideo = () => {
    const outputVideo = path.join(__dirname, 'output_video.mp4');

    ffmpeg()
        .input(path.join(imageDir, '%d.jpg'))
        .inputOptions('-framerate 30')
        .output(outputVideo)
        .outputOptions('-c:v libx264')
        .on('end', () => {
            console.log('Vidéo créée avec succès !');

            wss.clients.forEach(client => {
                if (client.readyState === WebSocket.OPEN) {
                    client.send('new-video');
                }
            });
        })
        .on('error', (err) => {
            console.log('Erreur lors de la création de la vidéo:', err);
        })
        .run();
};


app.get('/feed-video', (req, res) => {
    const videoPath = path.join(__dirname, 'output_video.mp4');
    res.sendFile(videoPath);
});

server.on('message', (msg, rinfo) => {
    console.log(`Reçu message de ${rinfo.address}:${rinfo.port}`);

    const imageFilePath = path.join(imageDir, `${imageCount}.jpg`);
    fs.writeFileSync(imageFilePath, msg);

    console.log(`Image ${imageCount}.jpg reçue et sauvegardée`);


    imageCount++;


    if (imageCount > 100) {
        createVideo();
        imageCount = 0;
    }
});


server.on('listening', () => {
    const address = server.address();
    console.log(`Serveur UDP en écoute sur ${address.address}:${address.port}`);
});


app.server = app.listen(httpPort, () => {
    console.log(`Serveur HTTP et WebSocket démarré sur http://localhost:${httpPort}`);
});

app.server.on('upgrade', (request, socket, head) => {
    wss.handleUpgrade(request, socket, head, (ws) => {
        wss.emit('connection', ws, request);
    });
});


server.bind(udpPort, udpHost);

html 页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Drone Video Feed</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #1a1a1a;
            color: #ffffff;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
        }

        h1 {
            margin-bottom: 20px;
            font-size: 2rem;
            text-shadow: 1px 1px 5px #00bcd4;
        }

        video {
            width: 80%;
            max-width: 600px;
            border: 2px solid #00bcd4;
            border-radius: 8px;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
        }
    </style>
</head>
<body>
<h1>Drone Video Feed</h1>
<video id="video" controls autoplay></video>

<script>
    const video = document.getElementById('video');
    const ws = new WebSocket('ws://localhost:3000');

    ws.onmessage = (event) => {
        const blob = new Blob([event.data], { type: 'video/mp4' });
        video.src = URL.createObjectURL(blob);
        video.play();
    };
</script>
</body>
</html>

请你帮我解决这个问题吗?

我尝试使用 websocket 但没有成功。 视频已正确创建,当我重新加载页面时,播放器将播放新视频

但是我本来可以看到直播,而不必一直重新加载我的页面

javascript html node.js ffmpeg
1个回答
0
投票

为了在不重新加载页面的情况下直播视频,WebRTC 是比 WebSockets 更适合实时视频流的技术。 WebRTC 允许低延迟、点对点通信,广泛用于直播场景。

以下是示例代码:

Node.js 服务器:

const express = require('express');
const dgram = require('dgram');
const { Server } = require('socket.io');
const http = require('http');

const app = express();
const server = http.createServer(app);
const io = new Server(server);

const udpPort = 15002;
const udpHost = '127.0.0.1';

const udpServer = dgram.createSocket('udp4');
let clients = [];

// Serve static HTML file
app.use(express.static(__dirname));

udpServer.on('message', (msg, rinfo) => {
    console.log(`Received message from ${rinfo.address}:${rinfo.port}`);

    // Broadcast the image frame to connected WebRTC clients
    clients.forEach(client => client.emit('video-frame', msg));
});

udpServer.on('listening', () => {
    const address = udpServer.address();
    console.log(`UDP Server listening on ${address.address}:${address.port}`);
});

io.on('connection', (socket) => {
    console.log('New WebRTC client connected');
    clients.push(socket);

    socket.on('disconnect', () => {
        console.log('WebRTC client disconnected');
        clients = clients.filter(client => client !== socket);
    });
});

// Start the servers
udpServer.bind(udpPort, udpHost);
server.listen(3000, () => {
    console.log('HTTP and WebSocket server running on http://localhost:3000');
});

HTML代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Drone Video Feed</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #1a1a1a;
            color: #ffffff;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
        }

        h1 {
            margin-bottom: 20px;
            font-size: 2rem;
            text-shadow: 1px 1px 5px #00bcd4;
        }

        video {
            width: 80%;
            max-width: 600px;
            border: 2px solid #00bcd4;
            border-radius: 8px;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
        }
    </style>
</head>
<body>
    <h1>Drone Video Feed</h1>
    <video id="video" autoplay muted></video>

    <script>
        const video = document.getElementById('video');
        const socket = io('http://localhost:3000');

        const mediaSource = new MediaSource();
        video.src = URL.createObjectURL(mediaSource);

        mediaSource.addEventListener('sourceopen', () => {
            const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E"');
            
            socket.on('video-frame', (frame) => {
                const blob = new Blob([frame], { type: 'video/mp4' });
                blob.arrayBuffer().then(buffer => {
                    sourceBuffer.appendBuffer(buffer);
                });
            });
        });
    </script>

    <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
</body>
</html>

希望这对您有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.