Skip to content

Commit

Permalink
Merge pull request TheWidlarzGroup#1306 from nickgzzjr/master
Browse files Browse the repository at this point in the history
Video Filters and Save Video
  • Loading branch information
cobarx authored Nov 21, 2018
2 parents 1207d45 + e9008cf commit 5e684d4
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions FilterType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ var styles = StyleSheet.create({
* [audioOnly](#audioonly)
* [bufferConfig](#bufferconfig)
* [controls](#controls)
* [filter](#filter)
* [fullscreen](#fullscreen)
* [fullscreenAutorotate](#fullscreenautorotate)
* [fullscreenOrientation](#fullscreenorientation)
Expand Down Expand Up @@ -299,6 +300,7 @@ var styles = StyleSheet.create({
### Methods
* [dismissFullscreenPlayer](#dismissfullscreenplayer)
* [presentFullscreenPlayer](#presentfullscreenplayer)
* [save](#save)
* [seek](#seek)

### Configurable props
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -671,6 +700,7 @@ Adjust the volume.

Platforms: all


### Event props

#### onAudioBecomingNoisy
Expand Down Expand Up @@ -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)`

Expand Down Expand Up @@ -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:
Expand Down
27 changes: 25 additions & 2 deletions Video.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
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({
Expand All @@ -11,7 +12,7 @@ const styles = StyleSheet.create({
},
});

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

export default class Video extends Component {

Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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([
Expand Down
20 changes: 19 additions & 1 deletion examples/video-caching/App.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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>
);
}
Expand All @@ -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",
Expand Down
4 changes: 2 additions & 2 deletions examples/video-caching/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ PODS:
- glog (0.3.4)
- React (0.56.0):
- React/Core (= 0.56.0)
- react-native-video/Video (3.1.0):
- react-native-video/Video (3.2.2):
- React
- react-native-video/VideoCaching (3.1.0):
- react-native-video/VideoCaching (3.2.2):
- DVAssetLoaderDelegate (~> 0.3.1)
- React
- react-native-video/Video
Expand Down
29 changes: 15 additions & 14 deletions examples/video-caching/ios/VideoCaching/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
Expand All @@ -38,19 +53,5 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSAppTransportSecurity</key>
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
</dict>
</plist>
3 changes: 3 additions & 0 deletions ios/Video/RCTVideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#import "RCTVideoPlayerViewController.h"
#import "RCTVideoPlayerViewControllerDelegate.h"
#import <React/RCTComponent.h>
#import <React/RCTBridgeModule.h>

#if __has_include(<react-native-video/RCTVideoCache.h>)
#import <react-native-video/RCTVideoCache.h>
Expand Down Expand Up @@ -41,4 +42,6 @@

- (AVPlayerViewController*)createPlayerViewController:(AVPlayer*)player withPlayerItem:(AVPlayerItem*)playerItem;

- (void)save:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject;

@end
Loading

0 comments on commit 5e684d4

Please sign in to comment.