You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-Native录制视频并通过Nginx RTMP模块上传至后端存储的方案问询

Yes, This Is Totally Feasible! Here's How to Implement It

I’ve worked on similar setups before, so let’s walk through the step-by-step solution tailored to your tech stack:

1. Configure Nginx with the RTMP Module

First, make sure your Nginx instance has the RTMP module compiled (most pre-built packages include it; if not, compile Nginx with --with-rtmp-module). Add this configuration to your nginx.conf:

rtmp {
    server {
        listen 1935; # Default RTMP port
        chunk_size 4096;

        application live {
            live on;
            record all; # Auto-record all incoming streams
            record_path /var/www/recorded-videos; # Local storage path for recordings
            record_format flv; # Use mp4 if you prefer that format
            record_unique on; # Generate unique filenames to avoid overwrites

            # Trigger your Express backend when a recording finishes
            on_record_done http://your-express-server/api/video/record-complete;
        }
    }
}

# Add an HTTP block to serve recorded videos publicly (optional but useful)
http {
    # ... your existing HTTP config ...
    server {
        listen 80;
        location /videos {
            alias /var/www/recorded-videos;
            autoindex on; # Optional, for browsing stored files
        }
    }
}

This setup accepts RTMP streams at rtmp://your-nginx-server/live/<your-stream-key> and saves recordings automatically. The on_record_done hook lets your backend know when a recording is ready to be tracked in MongoDB.

2. React Native Video Recording & RTMP Streaming

For the React Native side, use a library that handles video capture and RTMP streaming. react-native-rtmp-stream is a reliable choice. Here’s a simplified implementation with Redux integration:

First, install the library and set up permissions:

npm install react-native-rtmp-stream --save
  • For iOS: Add NSCameraUsageDescription and NSMicrophoneUsageDescription to your Info.plist.
  • For Android: Add <uses-permission android:name="android.permission.CAMERA" /> and <uses-permission android:name="android.permission.RECORD_AUDIO" /> to AndroidManifest.xml.

Then build your recorder component:

import React, { useRef } from 'react';
import { View, Button, Text } from 'react-native';
import { RtmpStream } from 'react-native-rtmp-stream';
import { useDispatch, useSelector } from 'react-redux';
import { startRecording, stopRecording, setRecordingError } from '../redux/actions/recordingActions';

const VideoRecorder = () => {
    const streamRef = useRef(null);
    const dispatch = useDispatch();
    const { isRecording, error } = useSelector(state => state.recording);

    const startStream = async () => {
        try {
            // Use a unique stream key (generate one per user/recording session)
            await streamRef.current.startStream('rtmp://your-nginx-server/live/user-123-session-456');
            dispatch(startRecording());
        } catch (err) {
            dispatch(setRecordingError(err.message));
        }
    };

    const stopStream = async () => {
        try {
            await streamRef.current.stopStream();
            dispatch(stopRecording());
        } catch (err) {
            dispatch(setRecordingError(err.message));
        }
    };

    return (
        <View>
            <RtmpStream
                ref={streamRef}
                style={{ width: '100%', height: 400 }}
                camera={1} // 1 for front camera, 0 for back
                audio={true}
                video={true}
            />
            {error && <Text style={{ color: 'red' }}>{error}</Text>}
            <Button 
                title={isRecording ? 'Stop Recording' : 'Start Recording'} 
                onPress={isRecording ? stopStream : startStream} 
            />
        </View>
    );
};

export default VideoRecorder;

3. Integrate with Node.js/Express & MongoDB

When Nginx finishes a recording, it sends a POST request to your Express endpoint. Use this to store recording metadata in MongoDB:

First, create a Mongoose model:

// models/VideoRecord.js
const mongoose = require('mongoose');

const videoRecordSchema = new mongoose.Schema({
    streamKey: { type: String, required: true },
    filePath: { type: String, required: true },
    fileName: { type: String, required: true },
    duration: { type: Number }, // Parsed from Nginx's payload
    createdAt: { type: Date, default: Date.now }
});

module.exports = mongoose.model('VideoRecord', videoRecordSchema);

Then create the Express endpoint:

// routes/videoRoutes.js
const express = require('express');
const router = express.Router();
const VideoRecord = require('../models/VideoRecord');

router.post('/api/video/record-complete', async (req, res) => {
    try {
        // Nginx sends data like: name, path, duration, etc.
        const { name, path, duration } = req.body;
        const streamKey = name.split('/')[1]; // Extract stream key from filename

        const newRecord = new VideoRecord({
            streamKey,
            filePath: path,
            fileName: name,
            duration: parseInt(duration)
        });

        await newRecord.save();
        res.status(200).send('Record saved successfully');
    } catch (err) {
        console.error('Error saving video record:', err);
        res.status(500).send('Internal server error');
    }
});

module.exports = router;

Don’t forget to mount this route in your Express app and connect to MongoDB as usual.

4. Redux State Management

Set up Redux to track recording state across your app:

// redux/actions/recordingActions.js
export const START_RECORDING = 'START_RECORDING';
export const STOP_RECORDING = 'STOP_RECORDING';
export const SET_RECORDING_ERROR = 'SET_RECORDING_ERROR';

export const startRecording = () => ({ type: START_RECORDING });
export const stopRecording = () => ({ type: STOP_RECORDING });
export const setRecordingError = (error) => ({ type: SET_RECORDING_ERROR, payload: error });

// redux/reducers/recordingReducer.js
import { START_RECORDING, STOP_RECORDING, SET_RECORDING_ERROR } from '../actions/recordingActions';

const initialState = {
    isRecording: false,
    error: null
};

const recordingReducer = (state = initialState, action) => {
    switch (action.type) {
        case START_RECORDING:
            return { ...state, isRecording: true, error: null };
        case STOP_RECORDING:
            return { ...state, isRecording: false };
        case SET_RECORDING_ERROR:
            return { ...state, error: action.payload };
        default:
            return state;
    }
};

export default recordingReducer;

Combine this reducer with your existing store setup, and you’re ready to go.

Key Tips for Production

  • Network Stability: Add logic to handle disconnections (auto-retry, user notifications) since RTMP relies on stable internet.
  • Security: Use Nginx’s on_publish hook to validate stream keys against your backend before allowing streams to start.
  • Scalability: If local storage isn’t enough, modify the Express endpoint to upload recordings to cloud storage (like S3) and update MongoDB with the cloud URL.
  • Format Conversion: Use ffmpeg to convert FLV to MP4 (trigger this via your Express backend after recording finishes).

内容的提问来源于stack exchange,提问作者Jor Khachatryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:49:56