feat: improve demo app and some optimizations for iOS
This commit is contained in:
parent
6640e69a81
commit
4496ad19e3
|
@ -2,6 +2,7 @@ package com.transparentvideo;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ import java.util.Dictionary;
|
||||||
|
|
||||||
public class TransparentVideoViewManager extends SimpleViewManager<View> {
|
public class TransparentVideoViewManager extends SimpleViewManager<View> {
|
||||||
public static final String REACT_CLASS = "TransparentVideoView";
|
public static final String REACT_CLASS = "TransparentVideoView";
|
||||||
|
private AlphaMovieView alphaMovieView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -29,6 +31,11 @@ public class TransparentVideoViewManager extends SimpleViewManager<View> {
|
||||||
|
|
||||||
@ReactProp(name = "src")
|
@ReactProp(name = "src")
|
||||||
public void setSrc(View view, ReadableMap src) {
|
public void setSrc(View view, ReadableMap src) {
|
||||||
|
if (this.alphaMovieView == null) {
|
||||||
|
alphaMovieView = new AlphaMovieView(view.getContext(), null); //new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||||
|
alphaMovieView.setAutoPlayAfterResume(true);
|
||||||
|
alphaMovieView.setVideoByUrl(src.getString("uri"));
|
||||||
|
}
|
||||||
view.setBackgroundColor(Color.BLUE);
|
view.setBackgroundColor(Color.BLUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -145,7 +145,6 @@
|
||||||
8FF5F75A1315DCD7F71FC708 /* Pods-TransparentVideoExample-TransparentVideoExampleTests.debug.xcconfig */,
|
8FF5F75A1315DCD7F71FC708 /* Pods-TransparentVideoExample-TransparentVideoExampleTests.debug.xcconfig */,
|
||||||
2A14A34D05389C0ADABA2876 /* Pods-TransparentVideoExample-TransparentVideoExampleTests.release.xcconfig */,
|
2A14A34D05389C0ADABA2876 /* Pods-TransparentVideoExample-TransparentVideoExampleTests.release.xcconfig */,
|
||||||
);
|
);
|
||||||
name = Pods;
|
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
@ -485,6 +484,7 @@
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = 37DHY4JC9T;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = TransparentVideoExample/Info.plist;
|
INFOPLIST_FILE = TransparentVideoExample/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -511,6 +511,7 @@
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = 37DHY4JC9T;
|
||||||
INFOPLIST_FILE = TransparentVideoExample/Info.plist;
|
INFOPLIST_FILE = TransparentVideoExample/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
|
|
@ -3,8 +3,10 @@ import React, { useEffect, useState } from 'react';
|
||||||
import { StyleSheet, View } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
import TransparentVideo from 'react-native-transparent-video';
|
import TransparentVideo from 'react-native-transparent-video';
|
||||||
|
|
||||||
const video1 = require('../assets/videos/background.mp4');
|
const video1 = require('../assets/videos/1.mp4');
|
||||||
const video2 = require('../assets/videos/playdoh-bat.mp4');
|
const video2 = require('../assets/videos/2.mp4');
|
||||||
|
const video3 = require('../assets/videos/3.mp4');
|
||||||
|
const video4 = require('../assets/videos/4.mp4');
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const [background, setBackground] = useState('blue');
|
const [background, setBackground] = useState('blue');
|
||||||
|
@ -31,6 +33,8 @@ export default () => {
|
||||||
<View style={{ ...styles.container, ...{ backgroundColor: background } }}>
|
<View style={{ ...styles.container, ...{ backgroundColor: background } }}>
|
||||||
<TransparentVideo source={video1} style={styles.video1} />
|
<TransparentVideo source={video1} style={styles.video1} />
|
||||||
<TransparentVideo source={video2} style={styles.video2} />
|
<TransparentVideo source={video2} style={styles.video2} />
|
||||||
|
<TransparentVideo source={video3} style={styles.video3} />
|
||||||
|
<TransparentVideo source={video4} style={styles.video4} />
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -56,4 +60,20 @@ const styles = StyleSheet.create({
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
},
|
},
|
||||||
|
video3: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
zIndex: 2,
|
||||||
|
},
|
||||||
|
video4: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
zIndex: 3,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -55,30 +55,76 @@ class TransparentVideoView : UIView {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load our player item
|
// Load our player item
|
||||||
let playerItem = createTransparentItem(url: itemUrl)
|
loadItem(url: itemUrl)
|
||||||
|
|
||||||
self.playerView!.loadPlayerItem(playerItem) { result in
|
|
||||||
switch result {
|
|
||||||
case .failure(let error):
|
|
||||||
return print("Something went wrong when loading our video", error)
|
|
||||||
|
|
||||||
case .success(let player):
|
|
||||||
// Finally, we can start playing
|
|
||||||
player.play()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Player Item Configuration
|
// MARK: - Player Item Configuration
|
||||||
|
|
||||||
func createTransparentItem(url: URL) -> AVPlayerItem {
|
private func loadItem(url: URL) {
|
||||||
|
setUpAsset(with: url) { [weak self] (asset: AVAsset) in
|
||||||
|
self?.setUpPlayerItem(with: asset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUpAsset(with url: URL, completion: ((_ asset: AVAsset) -> Void)?) {
|
||||||
let asset = AVAsset(url: url)
|
let asset = AVAsset(url: url)
|
||||||
let playerItem = AVPlayerItem(asset: asset)
|
asset.loadValuesAsynchronously(forKeys: ["metadata"]) {
|
||||||
// Set the video so that seeking also renders with transparency
|
var error: NSError? = nil
|
||||||
playerItem.seekingWaitsForVideoCompositionRendering = true
|
let status = asset.statusOfValue(forKey: "metadata", error: &error)
|
||||||
// Apply a video composition (which applies our custom filter)
|
switch status {
|
||||||
playerItem.videoComposition = createVideoComposition(for: asset)
|
case .loaded:
|
||||||
return playerItem
|
completion?(asset)
|
||||||
|
case .failed:
|
||||||
|
print(".failed")
|
||||||
|
case .cancelled:
|
||||||
|
print(".cancelled")
|
||||||
|
default:
|
||||||
|
print("default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUpPlayerItem(with asset: AVAsset) {
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
let playerItem = AVPlayerItem(asset: asset)
|
||||||
|
//playerItem.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.old, .new], context: nil)
|
||||||
|
playerItem.seekingWaitsForVideoCompositionRendering = true
|
||||||
|
// Apply a video composition (which applies our custom filter)
|
||||||
|
playerItem.videoComposition = self?.createVideoComposition(for: asset)
|
||||||
|
|
||||||
|
self?.playerView!.loadPlayerItem(playerItem) { result in
|
||||||
|
switch result {
|
||||||
|
case .failure(let error):
|
||||||
|
return print("Something went wrong when loading our video", error)
|
||||||
|
|
||||||
|
case .success(let player):
|
||||||
|
// Finally, we can start playing
|
||||||
|
player.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||||
|
if keyPath == #keyPath(AVPlayerItem.status) {
|
||||||
|
let status: AVPlayerItem.Status
|
||||||
|
if let statusNumber = change?[.newKey] as? NSNumber {
|
||||||
|
status = AVPlayerItem.Status(rawValue: statusNumber.intValue)!
|
||||||
|
} else {
|
||||||
|
status = .unknown
|
||||||
|
}
|
||||||
|
// Switch over status value
|
||||||
|
switch status {
|
||||||
|
case .readyToPlay:
|
||||||
|
print(".readyToPlay")
|
||||||
|
case .failed:
|
||||||
|
print(".failed")
|
||||||
|
case .unknown:
|
||||||
|
print(".unknown")
|
||||||
|
@unknown default:
|
||||||
|
print("@unknown default")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createVideoComposition(for asset: AVAsset) -> AVVideoComposition {
|
func createVideoComposition(for asset: AVAsset) -> AVVideoComposition {
|
||||||
|
|
Loading…
Reference in New Issue