Unverified Commit 5e684d40 authored by Hampton Maxwell's avatar Hampton Maxwell Committed by GitHub
Browse files

Merge pull request #1306 from nickgzzjr/master

Video Filters and Save Video
parents 1207d450 e9008cfa
Loading
Loading
Loading
Loading
+1 −0
Changes for CHANGELOG.md: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
* Switch useTextureView to default to `true` [#1286](https://github.com/react-native-community/react-native-video/pull/1286)
* Re-add fullscreenAutorotate prop [#1303](https://github.com/react-native-community/react-native-video/pull/1303)
* Make seek throw a useful error for NaN values [#1283](https://github.com/react-native-community/react-native-video/pull/1283)
* Video Filters and Save Video [#1306](https://github.com/react-native-community/react-native-video/pull/1306)
* Fix: volume should not change on onAudioFocusChange event [#1327](https://github.com/react-native-community/react-native-video/pull/1327)

### Version 3.2.0

FilterType.js

0 → 100644
+18 −0
Changes for FilterType.js: 18 added lines, 0 removed lines.
Original line number Diff line number Diff line
export default {
    NONE: '',
    INVERT: 'CIColorInvert',
    MONOCHROME: 'CIColorMonochrome',
    POSTERIZE: 'CIColorPosterize',
    FALSE: 'CIFalseColor',
    MAXIMUMCOMPONENT: 'CIMaximumComponent',
    MINIMUMCOMPONENT: 'CIMinimumComponent',
    CHROME: 'CIPhotoEffectChrome',
    FADE: 'CIPhotoEffectFade',
    INSTANT: 'CIPhotoEffectInstant',
    MONO: 'CIPhotoEffectMono',
    NOIR: 'CIPhotoEffectNoir',
    PROCESS: 'CIPhotoEffectProcess',
    TONAL: 'CIPhotoEffectTonal',
    TRANSFER: 'CIPhotoEffectTransfer',
    SEPIA: 'CISepiaTone'
};
+59 −0
Changes for README.md: 59 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -259,6 +259,7 @@ var styles = StyleSheet.create({
* [audioOnly](#audioonly)
* [bufferConfig](#bufferconfig)
* [controls](#controls)
* [filter](#filter)
* [fullscreen](#fullscreen)
* [fullscreenAutorotate](#fullscreenautorotate)
* [fullscreenOrientation](#fullscreenorientation)
@@ -299,6 +300,7 @@ var styles = StyleSheet.create({
### Methods
* [dismissFullscreenPlayer](#dismissfullscreenplayer)
* [presentFullscreenPlayer](#presentfullscreenplayer)
* [save](#save)
* [seek](#seek)

### Configurable props
@@ -352,6 +354,33 @@ Note on iOS, controls are always shown when in fullscreen mode.

Platforms: iOS, react-native-dom

#### filter
Add video filter
* **FilterType.NONE (default)** - No Filter
* **FilterType.INVERT** - CIColorInvert
* **FilterType.MONOCHROME** - CIColorMonochrome
* **FilterType.POSTERIZE** - CIColorPosterize
* **FilterType.FALSE** - CIFalseColor
* **FilterType.MAXIMUMCOMPONENT** - CIMaximumComponent
* **FilterType.MINIMUMCOMPONENT** - CIMinimumComponent
* **FilterType.CHROME** - CIPhotoEffectChrome
* **FilterType.FADE** - CIPhotoEffectFade
* **FilterType.INSTANT** - CIPhotoEffectInstant
* **FilterType.MONO** - CIPhotoEffectMono
* **FilterType.NOIR** - CIPhotoEffectNoir
* **FilterType.PROCESS** - CIPhotoEffectProcess
* **FilterType.TONAL** - CIPhotoEffectTonal
* **FilterType.TRANSFER** - CIPhotoEffectTransfer
* **FilterType.SEPIA** - CISepiaTone

For more details on these filters refer to the [iOS docs](https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/uid/TP30000136-SW55).

Notes: 
1. Using a filter can impact CPU usage. A workaround is to save the video with the filter and then load the saved video.
2. Video filter is currently not supported on HLS playlists.

Platforms: iOS

#### fullscreen
Controls whether the player enters fullscreen on play.
* **false (default)** - Don't display the video in fullscreen
@@ -671,6 +700,7 @@ Adjust the volume.

Platforms: all


### Event props

#### onAudioBecomingNoisy
@@ -879,6 +909,33 @@ this.player.presentFullscreenPlayer();

Platforms: Android ExoPlayer, Android MediaPlayer, iOS

#### save
`save(): Promise`

Save video to your Photos with current filter prop. Returns promise.

Example:
```
let response = await this.save();
let path = response.uri;
```

Notes:
 - Currently only supports highest quality export
 - Currently only supports MP4 export
 - Currently only supports exporting to user's cache directory with a generated UUID filename. 
 - User will need to remove the saved video through their Photos app
 - Works with cached videos as well. (Checkout video-caching example)
 - If the video is has not began buffering (e.g. there is no internet connection) then the save function will throw an error.
 - If the video is buffering then the save function promise will return after the video has finished buffering and processing.
 
Future: 
 - Will support multiple qualities through options
 - Will support more formats in the future through options
 - Will support custom directory and file name through options
 
Platforms: iOS

#### seek()
`seek(seconds)`

@@ -909,6 +966,8 @@ this.player.seek(120, 50); // Seek to 2 minutes with +/- 50 milliseconds accurac
Platforms: iOS




### iOS App Transport Security

- By default, iOS will only load encrypted (https) urls. If you want to load content from an unencrypted (http) source, you will need to modify your Info.plist file and add the following entry:
+25 −2
Changes for Video.js: 25 added lines, 2 removed lines.
Original line number Diff line number Diff line
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {StyleSheet, requireNativeComponent, NativeModules, View, ViewPropTypes, Image, Platform} from 'react-native';
import {StyleSheet, requireNativeComponent, NativeModules, View, ViewPropTypes, Image, Platform, findNodeHandle} from 'react-native';
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
import TextTrackType from './TextTrackType';
import FilterType from './FilterType';
import VideoResizeMode from './VideoResizeMode.js';

const styles = StyleSheet.create({
@@ -11,7 +12,7 @@ const styles = StyleSheet.create({
  },
});

export { TextTrackType };
export { TextTrackType, FilterType };

export default class Video extends Component {

@@ -73,6 +74,10 @@ export default class Video extends Component {
    this.setNativeProps({ fullscreen: false });
  };

  save = async (options?) => {
    return await NativeModules.VideoManager.save(options, findNodeHandle(this._root));
  }

  _assignRoot = (component) => {
    this._root = component;
  };
@@ -277,6 +282,24 @@ export default class Video extends Component {
}

Video.propTypes = {
  filter: PropTypes.oneOf([
      FilterType.NONE,
      FilterType.INVERT,
      FilterType.MONOCHROME,
      FilterType.POSTERIZE,
      FilterType.FALSE,
      FilterType.MAXIMUMCOMPONENT,
      FilterType.MINIMUMCOMPONENT,
      FilterType.CHROME,
      FilterType.FADE,
      FilterType.INSTANT,
      FilterType.MONO,
      FilterType.NOIR,
      FilterType.PROCESS,
      FilterType.TONAL,
      FilterType.TRANSFER,
      FilterType.SEPIA
  ]),
  /* Native only */
  src: PropTypes.object,
  seek: PropTypes.oneOfType([
+19 −1
Changes for examples/video-caching/App.ios.js: 19 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 */

import React, { Component } from "react";
import { StyleSheet, Text, View, Dimensions } from "react-native";
import { StyleSheet, Text, View, Dimensions, TouchableOpacity } from "react-native";
import Video from "react-native-video";

const { height, width } = Dimensions.get("screen");
@@ -28,6 +28,16 @@ export default class App extends Component<Props> {
          }}
          style={{ flex: 1, height, width }}
        />
        <TouchableOpacity
          onPress={async () => {
            let response = await this.player.save();
            let uri = response.uri;
            console.log("Download URI", uri);
          }}
          style={styles.button}
        >
          <Text style={{color: 'white'}}>Save</Text>
        </TouchableOpacity>
      </View>
    );
  }
@@ -40,6 +50,14 @@ const styles = StyleSheet.create({
    alignItems: "center",
    backgroundColor: "#F5FCFF"
  },
  button: {
    position: 'absolute',
    top: 50,
    right: 16,
    padding: 10,
    backgroundColor: '#9B2FAE',
    borderRadius: 8
  },
  welcome: {
    fontSize: 20,
    textAlign: "center",
Loading