react-native-vlc-media-player
                                
                                 react-native-vlc-media-player copied to clipboard
                                
                                    react-native-vlc-media-player copied to clipboard
                            
                            
                            
                        Record video from RTSP stream
RTSP Stream Recording Not Working
Description
I'm trying to record an RTSP stream in my React Native app using react-native-vlc-media-player. Playback works, but recording does not produce any video file on Android (tested on emulator). I have tried saving to both DocumentDirectoryPath and ExternalDirectoryPath using react-native-fs. The onRecordingCreated callback is never triggered.
I am able to successfully record and save videos with the emulators's camera, so there is no issue with permissions or something like that.
Environment
- Platform: Android (emulator)
- React Native version: 0.78.2
- react-native-vlc-media-player version: 1.0.87
- react-native-fs version: 2.20.0
Steps to Reproduce
- Use the example code below in a React Native project.
- Replace the EXAMPLE_RTSP_URLwith a valid RTSP stream.
- Run the app on an Android emulator.
- Start and stop recording using the provided buttons.
- Check the output directory (ExternalDirectoryPathorDocumentDirectoryPath) for the video file.
Expected Behavior
A video file (e.g., recording_example_<timestamp>.mp4) should be created in the specified directory after stopping the recording.
Actual Behavior
No video file is created in the output directory. No errors are thrown unless the recording methods themselves fail.
Example Code
import React, { useCallback, useRef, useState } from 'react';
import { Button, Platform, StyleSheet, Text, View } from 'react-native';
import { DocumentDirectoryPath, ExternalDirectoryPath } from 'react-native-fs';
import { VLCPlayer, VLCPlayerProps } from 'react-native-vlc-media-player';
/**
 * Example component for demonstrating RTSP stream recording in React Native.
 * This version contains NO sensitive data and is suitable for sharing in a public GitHub issue.
 *
 * - Uses react-native-vlc-media-player for RTSP playback and recording.
 * - Attempts to record to DocumentDirectoryPath or ExternalDirectoryPath.
 * - Shows the output path and basic error handling.
 *
 * Replace the RTSP URL with your own for actual use.
 */
const EXAMPLE_RTSP_URL = 'rtsp://your_rtsp_server_address/your_stream_path';
const VLC_PLAYER_INIT_OPTIONS: string[] = [
  '--rtsp-tcp',
  '--no-audio',
  '--verbose=2',
];
export const ExternalCameraAppExample: React.FC = () => {
  const playerRef = useRef<VLCPlayerProps | null>(null);
  const [isRecording, setIsRecording] = useState(false);
  const [recordingPath, setRecordingPath] = useState('');
  const [error, setError] = useState<string | null>(null);
  // Choose output path: DocumentDirectoryPath or ExternalDirectoryPath
  const outputPath =
    Platform.OS === 'android'
      ? `${ExternalDirectoryPath}/recording_example_${Date.now()}.mp4`
      : `${DocumentDirectoryPath}/recording_example_${Date.now()}.mp4`;
  const startRecording = useCallback(async () => {
    setError(null);
    setRecordingPath(outputPath);
    setIsRecording(true);
    try {
      await playerRef?.current?.startRecording?.(outputPath);
    } catch (e: any) {
      setIsRecording(false);
      setError('Failed to start recording: ' + (e?.message || e));
    }
  }, [outputPath]);
  const stopRecording = useCallback(async () => {
    setError(null);
    try {
      await playerRef?.current?.stopRecording?.();
      setIsRecording(false);
    } catch (e: any) {
      setIsRecording(false);
      setError('Failed to stop recording: ' + (e?.message || e));
    }
  }, []);
  return (
    <View style={styles.container}>
      <Text style={styles.title}>RTSP Recording Example</Text>
      <View style={styles.playerContainer}>
        <VLCPlayer
          ref={playerRef}
          source={{
            uri: EXAMPLE_RTSP_URL,
            initOptions: VLC_PLAYER_INIT_OPTIONS,
          }}
          autoplay={true}
          autoAspectRatio={true}
          resizeMode="cover"
          style={styles.cameraPreview}
          onError={e => setError('VLC Error: ' + JSON.stringify(e))}
        />
      </View>
      <View style={styles.controls}>
        {!isRecording ? (
          <Button title="Start Recording" onPress={startRecording} />
        ) : (
          <Button title="Stop Recording" onPress={stopRecording} />
        )}
      </View>
      <Text style={styles.info}>Recording path: {recordingPath}</Text>
      {error && <Text style={styles.error}>{error}</Text>}
      <Text style={styles.note}>
        Note: On Android, check the file at:
        {'\n'}
        {outputPath}
        {'\n'}
        (Use Device File Explorer or adb to verify.)
      </Text>
    </View>
  );
};
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    alignItems: 'center',
    backgroundColor: '#fff',
  },
  title: {
    fontWeight: 'bold',
    fontSize: 18,
    marginBottom: 12,
  },
  playerContainer: {
    width: '100%',
    height: 200,
    borderWidth: 1,
    borderColor: '#ccc',
    backgroundColor: '#000',
    marginBottom: 16,
  },
  cameraPreview: {
    width: '100%',
    height: '100%',
  },
  controls: {
    flexDirection: 'row',
    marginVertical: 16,
  },
  info: {
    fontSize: 12,
    color: '#333',
    marginBottom: 8,
  },
  error: {
    color: 'red',
    marginBottom: 8,
  },
  note: {
    fontSize: 12,
    color: '#666',
    marginTop: 16,
    textAlign: 'center',
  },
});
export default ExternalCameraAppExample;