/react-native-video-processing

Native Video editing/trimming/compressing :movie_camera: library for React-Native

Primary LanguageObjective-CMIT LicenseMIT

react-native-video-processing

Build Status semantic-release npm version npm package

Getting Started

npm install react-native-video-processing --save

You can check test just running

$ npm test or $ yarn test

Manual installation

Note: For RN 0.4x use 1.0 version, For RN 0.3x use  0.16

[Android]

  1. Open up android/app/src/main/java/[...]/MainApplication.java

  2. Add import com.shahenlibrary.RNVideoProcessingPackage; to the imports at the top of the file

  3. Add new new RNVideoProcessingPackage() to the list returned by the getPackages() method

  4. Append the following lines to android/settings.gradle:

include ':react-native-video-processing'
project(':react-native-video-processing').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video-processing/android')
  1. Insert the following lines inside the dependencies block in android/app/build.gradle:
    compile project(':react-native-video-processing')

[iOS]

  1. In Xcode, click the "Add Files to ".

  2. Go to node_modulesreact-native-video-processing/ios and add RNVideoProcessing directory.

  3. Make sure RNVideoProcessing is "under" the "top-level".

  4. Add GPUImage.xcodeproj from node_modules/react-native-video-processing/ios/GPUImage/framework directory to your project and make sure it is "under" the "top-level":

    Project Structure

  5. In XCode, in the project navigator, select your project.

    Add

    • CoreMedia
    • CoreVideo
    • OpenGLES
    • AVFoundation
    • QuartzCore
    • GPUImage
    • MobileCoreServices

    to your project's Build PhasesLink Binary With Libraries.

  6. Import RNVideoProcessing.h into your project_name-bridging-header.h.

  7. Clean and Run your project.

Usage

import React, { Component } from 'react';
import { View } from 'react-native';
import { VideoPlayer, Trimmer } from 'react-native-video-processing';

class App extends Component {
    trimVideo() {
        const options = {
            startTime: 0,
            endTime: 15,
            quality: VideoPlayer.Constants.quality.QUALITY_1280x720, // iOS only
            saveToCameraRoll: true, // default is false // iOS only
            saveWithCurrentDate: true, // default is false // iOS only
        };
        this.videoPlayerRef.trim(options)
            .then((newSource) => console.log(newSource))
            .catch(console.warn);
    }

    compressVideo() {
        const options = {
            width: 720,
            height: 1280,
            bitrateMultiplier: 3,
            saveToCameraRoll: true, // default is false, iOS only
            saveWithCurrentDate: true, // default is false, iOS only
            minimumBitrate: 300000,
            removeAudio: true, // default is false
        };
        this.videoPlayerRef.compress(options)
            .then((newSource) => console.log(newSource))
            .catch(console.warn);
    }

    getPreviewImageForSecond(second) {
        const maximumSize = { width: 640, height: 1024 }; // default is { width: 1080, height: 1080 } iOS only
        this.videoPlayerRef.getPreviewForSecond(second, maximumSize) // maximumSize is iOS only
        .then((base64String) => console.log('This is BASE64 of image', base64String))
        .catch(console.warn);
    }

    getVideoInfo() {
        this.videoPlayerRef.getVideoInfo()
        .then((info) => console.log(info))
        .catch(console.warn);
    }

    render() {
        return (
            <View style={{ flex: 1 }}>
                <VideoPlayer
                    ref={ref => this.videoPlayerRef = ref}
                    startTime={30}  // seconds
                    endTime={120}   // seconds
                    play={true}     // default false
                    replay={true}   // should player play video again if it's ended
                    rotate={true}   // use this prop to rotate video if it captured in landscape mode iOS only
                    source={'file:///sdcard/DCIM/....'}
                    playerWidth={300} // iOS only
                    playerHeight={500} // iOS only
                    style={{ backgroundColor: 'black' }}
                    resizeMode={VideoPlayer.Constants.resizeMode.CONTAIN}
                    onChange={({ nativeEvent }) => console.log({ nativeEvent })} // get Current time on every second
                />
                <Trimmer
                    source={'file:///sdcard/DCIM/....'}
                    height={100}
                    width={300}
                    onTrackerMove={(e) => console.log(e.currentTime)} // iOS only
                    currentTime={this.video.currentTime} // use this prop to set tracker position iOS only
                    themeColor={'white'} // iOS only
                    thumbWidth={30} // iOS only
                    trackerColor={'green'} // iOS only
                    onChange={(e) => console.log(e.startTime, e.endTime)}
                />
            </View>
        );
    }
}

or you can use ProcessingManager without mounting VideoPlayer component

import React, { Component } from 'react';
import { View } from 'react-native';
import { ProcessingManager } from 'react-native-video-processing';
export class App extends Component {
  componentWillMount() {
    const { source } = this.props;
    ProcessingManager.getVideoInfo(source)
      .then(({ duration, size, frameRate, bitrate }) => console.log(duration, size, frameRate, bitrate));

    ProcessingManager.trim(source, options) // like VideoPlayer trim options
          .then((data) => console.log(data));

    ProcessingManager.compress(source, options) // like VideoPlayer compress options
              .then((data) => console.log(data));

    ProcessingManager.reverse(source) // reverses the source video 
              .then((data) => console.log(data)); // returns the new file source

    ProcessingManager.boomerang(source) // creates a "boomerang" of the surce video (plays forward then plays backwards)
              .then((data) => console.log(data)); // returns the new file source

    const maximumSize = { width: 100, height: 200 };
    ProcessingManager.getPreviewForSecond(source, forSecond, maximumSize)
      .then((data) => console.log(data))
  }
  render() {
    return <View />;
  }
}

How to setup Library

Setup

For Android:

add these lines

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

to your AndroidManifest.xml

Contributing

  1. Please follow the eslint style guide.
  2. Please commit with $ npm run commit

Roadmap

  1. Use FFMpeg instead of MP4Parser
  2. Add ability to add GLSL filters
  3. Android should be able to compress video
  4. More processing options
  5. Create native trimmer component for Android
  6. Provide Standalone API
  7. Describe API methods with parameters in README