如何基于Janus WebRTC创建视频会议应用房间及Node+ReactJS项目房间API开发求助
Hey Tony, let's walk through this clearly—since you're new to this stack, I'll break it down into actionable steps for both room creation with Janus WebRTC and your Node.js/React setup.
First, Janus uses plugins to handle specific features, and for video conferencing, you'll rely on the built-in videoroom plugin. Creating a room involves sending a control message to Janus's API endpoint (usually http://your-janus-server:8088/janus) to initialize the room.
Let's start with the backend—you already have signup/signin routes, so we'll add the room creation logic that talks to Janus directly.
Step 2.1: Setup Dependencies
First, install packages to handle HTTP requests to Janus and session management:
npm install axios express jsonwebtoken bcryptjs cors
Step 2.2: Room Creation Endpoint
Here's a simplified example of a /create-room route that authenticates the user (using JWT) and sends a room creation request to Janus:
const express = require('express'); const axios = require('axios'); const jwt = require('jsonwebtoken'); const cors = require('cors'); const router = express.Router(); // Enable CORS for frontend requests router.use(cors()); // Middleware to verify JWT (protect room creation route) const authenticateToken = (req, res, next) => { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; if (!token) return res.sendStatus(401); jwt.verify(token, process.env.JWT_SECRET, (err, user) => { if (err) return res.sendStatus(403); req.user = user; next(); }); }; // POST /api/create-room router.post('/create-room', authenticateToken, async (req, res) => { const { roomName, description } = req.body; const janusUrl = process.env.JANUS_API_URL; // e.g., "http://localhost:8088/janus" try { // 1. Create a temporary Janus session const sessionResponse = await axios.post(`${janusUrl}`, { janus: 'create', transaction: Date.now().toString() }); const sessionId = sessionResponse.data.data.id; // 2. Attach to the videoroom plugin const attachResponse = await axios.post(`${janusUrl}`, { janus: 'attach', plugin: 'janus.plugin.videoroom', session_id: sessionId, transaction: Date.now().toString() }); const handleId = attachResponse.data.data.id; // 3. Send room creation command const createRoomResponse = await axios.post(`${janusUrl}`, { janus: 'message', body: { request: 'create', room: Math.floor(Math.random() * 9000) + 1000, // Random 4-digit room ID description: description, name: roomName, publishers: 10, // Max number of video publishers bitrate: 1024000 // Default bitrate for streams }, session_id: sessionId, handle_id: handleId, transaction: Date.now().toString() }); // Cleanup: Detach from plugin and destroy session (good practice) await axios.post(`${janusUrl}`, { janus: 'detach', session_id: sessionId, handle_id: handleId, transaction: Date.now().toString() }); await axios.post(`${janusUrl}`, { janus: 'destroy', session_id: sessionId, transaction: Date.now().toString() }); // Return room details to frontend res.status(200).json({ success: true, roomId: createRoomResponse.data.data.room, roomName: roomName }); } catch (error) { console.error('Error creating Janus room:', error.response?.data || error.message); res.status(500).json({ success: false, message: 'Failed to create room' }); } }); module.exports = router;
Step 2.3: Quick Note for Auth Routes
Make sure your signup/signin routes generate a JWT with user details—this is what the authenticateToken middleware uses to ensure only logged-in users can create rooms. For example, a basic signin route:
router.post('/signin', async (req, res) => { // Fetch user from your database const user = await User.findOne({ email: req.body.email }); if (!user || !await bcrypt.compare(req.body.password, user.password)) { return res.status(401).json({ message: 'Invalid credentials' }); } // Generate JWT token const token = jwt.sign({ userId: user._id, email: user.email }, process.env.JWT_SECRET, { expiresIn: '24h' }); res.json({ token }); });
On the React side, you'll need to call your backend's /create-room route, then use the Janus JavaScript library to join the room.
Step 3.1: Add Janus JS Library
Include the Janus script in your public/index.html:
<script src="https://janus.conf.meetecho.com/janus.js"></script>
(For production, download the script locally to avoid relying on external CDNs.)
Step 3.2: Component for Creating/Joining Rooms
Here's a simplified React component that handles room creation and joining:
import { useState } from 'react'; import axios from 'axios'; function VideoRoom() { const [roomName, setRoomName] = useState(''); const [description, setDescription] = useState(''); const [roomId, setRoomId] = useState(null); const [janusInstance, setJanusInstance] = useState(null); // Get JWT from local storage (after user logs in) const token = localStorage.getItem('authToken'); const createRoom = async () => { if (!token) { alert('Please log in first!'); return; } try { const response = await axios.post('/api/create-room', { roomName, description }, { headers: { Authorization: `Bearer ${token}` } }); setRoomId(response.data.roomId); alert(`Room created successfully! ID: ${response.data.roomId}`); } catch (error) { console.error('Error creating room:', error); alert('Failed to create room. Check console for details.'); } }; const joinRoom = () => { if (!roomId) return; // Initialize Janus connection const janus = new Janus({ server: 'http://your-janus-server:8088/janus', success: () => { // Attach to videoroom plugin janus.attach({ plugin: 'janus.plugin.videoroom', success: (handle) => { // Send join request as a publisher handle.send({ message: { request: 'join', room: parseInt(roomId), ptype: 'publisher', display: 'Your Display Name' }, success: (result) => { console.log('Joined room:', result); // Handle local video stream handle.createOffer({ media: { video: true, audio: true }, success: (jsep) => { handle.send({ message: { request: 'configure' }, jsep: jsep }); } }); // Listen for remote feeds handle.on('remotefeed', (feed) => { feed.attach(document.getElementById('remote-video')); }); }, error: (err) => { console.error('Error joining room:', err); } }); }, error: (err) => { console.error('Error attaching to plugin:', err); } }); }, error: (err) => { console.error('Error connecting to Janus:', err); } }); setJanusInstance(janus); }; return ( <div className="video-room-container"> <h2>Video Conference Room</h2> <div className="create-room-form"> <input type="text" placeholder="Room Name" value={roomName} onChange={(e) => setRoomName(e.target.value)} /> <input type="text" placeholder="Room Description" value={description} onChange={(e) => setDescription(e.target.value)} /> <button onClick={createRoom}>Create New Room</button> </div> {roomId && ( <div className="room-controls"> <p>Room ID: <strong>{roomId}</strong></p> <button onClick={joinRoom}>Join Room</button> <div className="video-container"> <video id="local-video" autoPlay playsInline muted></video> <video id="remote-video" autoPlay playsInline></video> </div> </div> )} </div> ); } export default VideoRoom;
- CORS Errors: Janus runs on a different port, so ensure your Node.js backend uses the
corspackage, and update Janus's config (janus.cfg) to allow cross-origin requests (setcors_allowed_originsto your frontend URL). - Janus Plugin Issues: Double-check that the
videoroomplugin is enabled in Janus's config folder (look forjanus.plugin.videoroom.jcfg). - Session Expiry: Janus sessions have a default timeout—for production, consider keeping a persistent session from your backend instead of creating a new one per room.
- Debugging: Add detailed logging in both backend and frontend to trace failures (e.g., Janus server unreachable, invalid room parameters).
内容的提问来源于stack exchange,提问作者Tony George

