@react-native-ohos/react-native-skia 1.3.10 → 1.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +6 -6
- package/README.md +8 -8
- package/harmony/skia.har +0 -0
- package/package.json +136 -134
- package/scripts/setup-canvaskit.js +105 -105
- package/src/external/reanimated/Video.ts +17 -0
- package/src/external/reanimated/useVideo.ts +179 -170
- package/src/index.ts +3 -3
- package/lib/commonjs/external/reanimated/useVideo.js +0 -155
- package/lib/commonjs/external/reanimated/useVideo.js.map +0 -1
- package/lib/commonjs/index.js +0 -28
- package/lib/commonjs/index.js.map +0 -1
- package/lib/module/external/reanimated/useVideo.js +0 -147
- package/lib/module/external/reanimated/useVideo.js.map +0 -1
- package/lib/module/index.js +0 -4
- package/lib/module/index.js.map +0 -1
- package/lib/typescript/index.d.ts +0 -1
- package/lib/typescript/jestEnv.d.mts +0 -5
- package/lib/typescript/jestSetup.d.mts +0 -1
- package/lib/typescript/jestSetup.d.ts +0 -1
- package/lib/typescript/src/external/reanimated/useVideo.d.ts +0 -22
- package/lib/typescript/src/index.d.ts +0 -3
|
@@ -1,170 +1,179 @@
|
|
|
1
|
-
import type { SharedValue, FrameInfo } from "react-native-reanimated";
|
|
2
|
-
import { useEffect, useMemo } from "react";
|
|
3
|
-
|
|
4
|
-
import type { SkImage
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
seek
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
lastTimestamp.value = currentTimestamp;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (
|
|
145
|
-
(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
};
|
|
170
|
-
|
|
1
|
+
import type { SharedValue, FrameInfo } from "react-native-reanimated";
|
|
2
|
+
import { useEffect, useMemo } from "react";
|
|
3
|
+
|
|
4
|
+
import type { SkImage } from "@shopify/react-native-skia";
|
|
5
|
+
import type { Video } from "./Video";
|
|
6
|
+
|
|
7
|
+
import { Platform } from "@shopify/react-native-skia/src/Platform/Platform";
|
|
8
|
+
|
|
9
|
+
import Rea from "@shopify/react-native-skia/src/external/reanimated/ReanimatedProxy";
|
|
10
|
+
import { useVideoLoading } from "@shopify/react-native-skia/src/external/reanimated/useVideoLoading";
|
|
11
|
+
|
|
12
|
+
type Animated<T> = SharedValue<T> | T;
|
|
13
|
+
|
|
14
|
+
interface PlaybackOptions {
|
|
15
|
+
looping: Animated<boolean>;
|
|
16
|
+
paused: Animated<boolean>;
|
|
17
|
+
seek: Animated<number | null>;
|
|
18
|
+
volume: Animated<number>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const currentSKImageFrames: SkImage[] = [];
|
|
22
|
+
|
|
23
|
+
const copyFrameOnAndroid = (currentFrame: SharedValue<SkImage | null>) => {
|
|
24
|
+
"worklet";
|
|
25
|
+
// on android we need to copy the texture before it's invalidated
|
|
26
|
+
if (Platform.OS === "android" || Platform.OS === "harmony") {
|
|
27
|
+
const tex = currentFrame.value;
|
|
28
|
+
if (tex) {
|
|
29
|
+
currentFrame.value = tex.makeNonTextureImage();
|
|
30
|
+
//currentSKImageFrames.push(currentFrame.value);
|
|
31
|
+
//console.log("push OK");
|
|
32
|
+
tex.dispose();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const setFrame = (video: Video, currentFrame: SharedValue<SkImage | null>) => {
|
|
38
|
+
"worklet";
|
|
39
|
+
console.log("nextImage");
|
|
40
|
+
const img = video.nextImage();
|
|
41
|
+
if (img) {
|
|
42
|
+
if (currentFrame.value) {
|
|
43
|
+
currentFrame.value.dispose();
|
|
44
|
+
}
|
|
45
|
+
currentFrame.value = img;
|
|
46
|
+
copyFrameOnAndroid(currentFrame);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const defaultOptions = {
|
|
51
|
+
looping: true,
|
|
52
|
+
paused: false,
|
|
53
|
+
seek: null,
|
|
54
|
+
currentTime: 0,
|
|
55
|
+
volume: 0,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const useOption = <T>(value: Animated<T>) => {
|
|
59
|
+
"worklet";
|
|
60
|
+
// TODO: only create defaultValue is needed (via makeMutable)
|
|
61
|
+
const defaultValue = Rea.useSharedValue(
|
|
62
|
+
Rea.isSharedValue(value) ? value.value : value
|
|
63
|
+
);
|
|
64
|
+
return Rea.isSharedValue(value) ? value : defaultValue;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const disposeVideo = (video: Video | null) => {
|
|
68
|
+
"worklet";
|
|
69
|
+
video?.dispose();
|
|
70
|
+
video?.stop();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const useVideo = (
|
|
74
|
+
source: string | null,
|
|
75
|
+
userOptions?: Partial<PlaybackOptions>
|
|
76
|
+
) => {
|
|
77
|
+
const video = useVideoLoading(source);
|
|
78
|
+
const isPaused = useOption(userOptions?.paused ?? defaultOptions.paused);
|
|
79
|
+
const looping = useOption(userOptions?.looping ?? defaultOptions.looping);
|
|
80
|
+
const seek = useOption(userOptions?.seek ?? defaultOptions.seek);
|
|
81
|
+
const volume = useOption(userOptions?.volume ?? defaultOptions.volume);
|
|
82
|
+
const currentFrame = Rea.useSharedValue<null | SkImage>(null);
|
|
83
|
+
const currentTime = Rea.useSharedValue(0);
|
|
84
|
+
const lastTimestamp = Rea.useSharedValue(-1);
|
|
85
|
+
const duration = useMemo(() => video?.duration() ?? 0, [video]);
|
|
86
|
+
const framerate = useMemo(
|
|
87
|
+
() => (Platform.OS === "web" ? -1 : video?.framerate() ?? 0),
|
|
88
|
+
[video]
|
|
89
|
+
);
|
|
90
|
+
const size = useMemo(() => video?.size() ?? { width: 0, height: 0 }, [video]);
|
|
91
|
+
const rotation = useMemo(() => video?.rotation() ?? 0, [video]);
|
|
92
|
+
const frameDuration = 1000 / framerate;
|
|
93
|
+
const currentFrameDuration = Math.floor(frameDuration);
|
|
94
|
+
Rea.useAnimatedReaction(
|
|
95
|
+
() => isPaused.value,
|
|
96
|
+
(paused) => {
|
|
97
|
+
if (paused) {
|
|
98
|
+
video?.pause();
|
|
99
|
+
} else {
|
|
100
|
+
lastTimestamp.value = -1;
|
|
101
|
+
video?.play();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
Rea.useAnimatedReaction(
|
|
106
|
+
() => seek.value,
|
|
107
|
+
(value) => {
|
|
108
|
+
if (value !== null) {
|
|
109
|
+
video?.seek(value);
|
|
110
|
+
currentTime.value = value;
|
|
111
|
+
seek.value = null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
Rea.useAnimatedReaction(
|
|
116
|
+
() => volume.value,
|
|
117
|
+
(value) => {
|
|
118
|
+
video?.setVolume(value);
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
Rea.useAnimatedReaction(
|
|
123
|
+
() => looping.value,
|
|
124
|
+
(value) => {
|
|
125
|
+
video?.setLoop(value);
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
Rea.useFrameCallback(async (frameInfo: FrameInfo) => {
|
|
130
|
+
"worklet";
|
|
131
|
+
if (!video) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (isPaused.value) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const currentTimestamp = frameInfo.timestamp;
|
|
138
|
+
if (lastTimestamp.value === -1) {
|
|
139
|
+
lastTimestamp.value = currentTimestamp;
|
|
140
|
+
}
|
|
141
|
+
const delta = currentTimestamp - lastTimestamp.value;
|
|
142
|
+
const isOver = currentTime.value + delta > duration;
|
|
143
|
+
|
|
144
|
+
if (isOver && looping.value) {
|
|
145
|
+
console.log("in if seek");
|
|
146
|
+
seek.value = 0;
|
|
147
|
+
currentTime.value = seek.value;
|
|
148
|
+
lastTimestamp.value = currentTimestamp;
|
|
149
|
+
}
|
|
150
|
+
// On Web the framerate is uknown.
|
|
151
|
+
// This could be optimized by using requestVideoFrameCallback (Chrome only)
|
|
152
|
+
|
|
153
|
+
if (
|
|
154
|
+
(delta > currentFrameDuration * 3 && !isOver) ||
|
|
155
|
+
Platform.OS === "web"
|
|
156
|
+
) {
|
|
157
|
+
//console.log(`当前时间:${currentTime.value},时间间隔:${delta},当前帧持续时间:${currentFrameDuration}`)
|
|
158
|
+
setFrame(video, currentFrame);
|
|
159
|
+
currentTime.value += delta;
|
|
160
|
+
lastTimestamp.value = currentTimestamp;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
return () => {
|
|
166
|
+
// TODO: should video simply be a shared value instead?
|
|
167
|
+
Rea.runOnUI(disposeVideo)(video);
|
|
168
|
+
};
|
|
169
|
+
}, [video]);
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
currentFrame,
|
|
173
|
+
currentTime,
|
|
174
|
+
duration,
|
|
175
|
+
framerate,
|
|
176
|
+
rotation,
|
|
177
|
+
size,
|
|
178
|
+
};
|
|
179
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "@shopify/react-native-skia/src/skia/NativeSetup";
|
|
2
|
-
export { JsiSkImage } from "@shopify/react-native-skia";
|
|
3
|
-
export * from "@shopify/react-native-skia";
|
|
1
|
+
import "@shopify/react-native-skia/src/skia/NativeSetup";
|
|
2
|
+
export { JsiSkImage } from "@shopify/react-native-skia";
|
|
3
|
+
export * from "@shopify/react-native-skia";
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.useVideo = exports.currentSKImageFrames = void 0;
|
|
7
|
-
var _react = require("react");
|
|
8
|
-
var _Platform = require("@shopify/react-native-skia/src/Platform/Platform");
|
|
9
|
-
var _ReanimatedProxy = _interopRequireDefault(require("@shopify/react-native-skia/src/external/reanimated/ReanimatedProxy"));
|
|
10
|
-
var _useVideoLoading = require("@shopify/react-native-skia/src/external/reanimated/useVideoLoading");
|
|
11
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
-
const currentSKImageFrames = exports.currentSKImageFrames = [];
|
|
13
|
-
const copyFrameOnAndroid = currentFrame => {
|
|
14
|
-
"worklet";
|
|
15
|
-
|
|
16
|
-
// on android we need to copy the texture before it's invalidated
|
|
17
|
-
if (_Platform.Platform.OS === "android" || _Platform.Platform.OS === "harmony") {
|
|
18
|
-
const tex = currentFrame.value;
|
|
19
|
-
if (tex) {
|
|
20
|
-
currentFrame.value = tex.makeNonTextureImage();
|
|
21
|
-
//currentSKImageFrames.push(currentFrame.value);
|
|
22
|
-
//console.log("push OK");
|
|
23
|
-
tex.dispose();
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
const setFrame = (video, currentFrame) => {
|
|
28
|
-
"worklet";
|
|
29
|
-
|
|
30
|
-
console.log("nextImage");
|
|
31
|
-
const img = video.nextImage();
|
|
32
|
-
if (img) {
|
|
33
|
-
if (currentFrame.value) {
|
|
34
|
-
currentFrame.value.dispose();
|
|
35
|
-
}
|
|
36
|
-
currentFrame.value = img;
|
|
37
|
-
copyFrameOnAndroid(currentFrame);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
const defaultOptions = {
|
|
41
|
-
looping: true,
|
|
42
|
-
paused: false,
|
|
43
|
-
seek: null,
|
|
44
|
-
currentTime: 0,
|
|
45
|
-
volume: 0
|
|
46
|
-
};
|
|
47
|
-
const useOption = value => {
|
|
48
|
-
"worklet";
|
|
49
|
-
|
|
50
|
-
// TODO: only create defaultValue is needed (via makeMutable)
|
|
51
|
-
const defaultValue = _ReanimatedProxy.default.useSharedValue(_ReanimatedProxy.default.isSharedValue(value) ? value.value : value);
|
|
52
|
-
return _ReanimatedProxy.default.isSharedValue(value) ? value : defaultValue;
|
|
53
|
-
};
|
|
54
|
-
const disposeVideo = video => {
|
|
55
|
-
"worklet";
|
|
56
|
-
|
|
57
|
-
video === null || video === void 0 || video.dispose();
|
|
58
|
-
};
|
|
59
|
-
const useVideo = (source, userOptions) => {
|
|
60
|
-
var _userOptions$paused, _userOptions$looping, _userOptions$seek, _userOptions$volume;
|
|
61
|
-
const video = (0, _useVideoLoading.useVideoLoading)(source);
|
|
62
|
-
const isPaused = useOption((_userOptions$paused = userOptions === null || userOptions === void 0 ? void 0 : userOptions.paused) !== null && _userOptions$paused !== void 0 ? _userOptions$paused : defaultOptions.paused);
|
|
63
|
-
const looping = useOption((_userOptions$looping = userOptions === null || userOptions === void 0 ? void 0 : userOptions.looping) !== null && _userOptions$looping !== void 0 ? _userOptions$looping : defaultOptions.looping);
|
|
64
|
-
const seek = useOption((_userOptions$seek = userOptions === null || userOptions === void 0 ? void 0 : userOptions.seek) !== null && _userOptions$seek !== void 0 ? _userOptions$seek : defaultOptions.seek);
|
|
65
|
-
const volume = useOption((_userOptions$volume = userOptions === null || userOptions === void 0 ? void 0 : userOptions.volume) !== null && _userOptions$volume !== void 0 ? _userOptions$volume : defaultOptions.volume);
|
|
66
|
-
const currentFrame = _ReanimatedProxy.default.useSharedValue(null);
|
|
67
|
-
const currentTime = _ReanimatedProxy.default.useSharedValue(0);
|
|
68
|
-
const lastTimestamp = _ReanimatedProxy.default.useSharedValue(-1);
|
|
69
|
-
const duration = (0, _react.useMemo)(() => {
|
|
70
|
-
var _video$duration;
|
|
71
|
-
return (_video$duration = video === null || video === void 0 ? void 0 : video.duration()) !== null && _video$duration !== void 0 ? _video$duration : 0;
|
|
72
|
-
}, [video]);
|
|
73
|
-
const framerate = (0, _react.useMemo)(() => {
|
|
74
|
-
var _video$framerate;
|
|
75
|
-
return _Platform.Platform.OS === "web" ? -1 : (_video$framerate = video === null || video === void 0 ? void 0 : video.framerate()) !== null && _video$framerate !== void 0 ? _video$framerate : 0;
|
|
76
|
-
}, [video]);
|
|
77
|
-
const size = (0, _react.useMemo)(() => {
|
|
78
|
-
var _video$size;
|
|
79
|
-
return (_video$size = video === null || video === void 0 ? void 0 : video.size()) !== null && _video$size !== void 0 ? _video$size : {
|
|
80
|
-
width: 0,
|
|
81
|
-
height: 0
|
|
82
|
-
};
|
|
83
|
-
}, [video]);
|
|
84
|
-
const rotation = (0, _react.useMemo)(() => {
|
|
85
|
-
var _video$rotation;
|
|
86
|
-
return (_video$rotation = video === null || video === void 0 ? void 0 : video.rotation()) !== null && _video$rotation !== void 0 ? _video$rotation : 0;
|
|
87
|
-
}, [video]);
|
|
88
|
-
const frameDuration = 1000 / framerate;
|
|
89
|
-
const currentFrameDuration = Math.floor(frameDuration);
|
|
90
|
-
_ReanimatedProxy.default.useAnimatedReaction(() => isPaused.value, paused => {
|
|
91
|
-
if (paused) {
|
|
92
|
-
video === null || video === void 0 || video.pause();
|
|
93
|
-
} else {
|
|
94
|
-
lastTimestamp.value = -1;
|
|
95
|
-
video === null || video === void 0 || video.play();
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
_ReanimatedProxy.default.useAnimatedReaction(() => seek.value, value => {
|
|
99
|
-
if (value !== null) {
|
|
100
|
-
video === null || video === void 0 || video.seek(value);
|
|
101
|
-
currentTime.value = value;
|
|
102
|
-
seek.value = null;
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
_ReanimatedProxy.default.useAnimatedReaction(() => volume.value, value => {
|
|
106
|
-
video === null || video === void 0 || video.setVolume(value);
|
|
107
|
-
});
|
|
108
|
-
_ReanimatedProxy.default.useFrameCallback(async frameInfo => {
|
|
109
|
-
"worklet";
|
|
110
|
-
|
|
111
|
-
if (!video) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
if (isPaused.value) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
const currentTimestamp = frameInfo.timestamp;
|
|
118
|
-
if (lastTimestamp.value === -1) {
|
|
119
|
-
lastTimestamp.value = currentTimestamp;
|
|
120
|
-
}
|
|
121
|
-
const delta = currentTimestamp - lastTimestamp.value;
|
|
122
|
-
const isOver = currentTime.value + delta > duration;
|
|
123
|
-
if (isOver && looping.value) {
|
|
124
|
-
console.log("in if seek");
|
|
125
|
-
seek.value = 0;
|
|
126
|
-
currentTime.value = seek.value;
|
|
127
|
-
lastTimestamp.value = currentTimestamp;
|
|
128
|
-
}
|
|
129
|
-
// On Web the framerate is uknown.
|
|
130
|
-
// This could be optimized by using requestVideoFrameCallback (Chrome only)
|
|
131
|
-
|
|
132
|
-
if (delta > currentFrameDuration * 3 && !isOver || _Platform.Platform.OS === "web") {
|
|
133
|
-
//console.log(`当前时间:${currentTime.value},时间间隔:${delta},当前帧持续时间:${currentFrameDuration}`)
|
|
134
|
-
setFrame(video, currentFrame);
|
|
135
|
-
currentTime.value += delta;
|
|
136
|
-
lastTimestamp.value = currentTimestamp;
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
(0, _react.useEffect)(() => {
|
|
140
|
-
return () => {
|
|
141
|
-
// TODO: should video simply be a shared value instead?
|
|
142
|
-
_ReanimatedProxy.default.runOnUI(disposeVideo)(video);
|
|
143
|
-
};
|
|
144
|
-
}, [video]);
|
|
145
|
-
return {
|
|
146
|
-
currentFrame,
|
|
147
|
-
currentTime,
|
|
148
|
-
duration,
|
|
149
|
-
framerate,
|
|
150
|
-
rotation,
|
|
151
|
-
size
|
|
152
|
-
};
|
|
153
|
-
};
|
|
154
|
-
exports.useVideo = useVideo;
|
|
155
|
-
//# sourceMappingURL=useVideo.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_Platform","_ReanimatedProxy","_interopRequireDefault","_useVideoLoading","e","__esModule","default","currentSKImageFrames","exports","copyFrameOnAndroid","currentFrame","Platform","OS","tex","value","makeNonTextureImage","dispose","setFrame","video","console","log","img","nextImage","defaultOptions","looping","paused","seek","currentTime","volume","useOption","defaultValue","Rea","useSharedValue","isSharedValue","disposeVideo","useVideo","source","userOptions","_userOptions$paused","_userOptions$looping","_userOptions$seek","_userOptions$volume","useVideoLoading","isPaused","lastTimestamp","duration","useMemo","_video$duration","framerate","_video$framerate","size","_video$size","width","height","rotation","_video$rotation","frameDuration","currentFrameDuration","Math","floor","useAnimatedReaction","pause","play","setVolume","useFrameCallback","frameInfo","currentTimestamp","timestamp","delta","isOver","useEffect","runOnUI"],"sources":["useVideo.ts"],"sourcesContent":["import type { SharedValue, FrameInfo } from \"react-native-reanimated\";\r\nimport { useEffect, useMemo } from \"react\";\r\n\r\nimport type { SkImage, Video } from \"@shopify/react-native-skia\";\r\nimport { Platform } from \"@shopify/react-native-skia/src/Platform/Platform\";\r\n\r\nimport Rea from \"@shopify/react-native-skia/src/external/reanimated/ReanimatedProxy\";\r\nimport { useVideoLoading } from \"@shopify/react-native-skia/src/external/reanimated/useVideoLoading\";\r\n\r\ntype Animated<T> = SharedValue<T> | T;\r\n\r\ninterface PlaybackOptions {\r\n looping: Animated<boolean>;\r\n paused: Animated<boolean>;\r\n seek: Animated<number | null>;\r\n volume: Animated<number>;\r\n}\r\n\r\nexport const currentSKImageFrames: SkImage[] = [];\r\n\r\nconst copyFrameOnAndroid = (currentFrame: SharedValue<SkImage | null>) => {\r\n \"worklet\";\r\n // on android we need to copy the texture before it's invalidated\r\n if (Platform.OS === \"android\" || Platform.OS === \"harmony\") {\r\n const tex = currentFrame.value;\r\n if (tex) {\r\n currentFrame.value = tex.makeNonTextureImage();\r\n //currentSKImageFrames.push(currentFrame.value);\r\n //console.log(\"push OK\");\r\n tex.dispose();\r\n }\r\n }\r\n};\r\n\r\nconst setFrame = (video: Video, currentFrame: SharedValue<SkImage | null>) => {\r\n \"worklet\";\r\n console.log(\"nextImage\");\r\n const img = video.nextImage();\r\n if (img) {\r\n if (currentFrame.value) {\r\n currentFrame.value.dispose();\r\n }\r\n currentFrame.value = img;\r\n copyFrameOnAndroid(currentFrame);\r\n }\r\n};\r\n\r\nconst defaultOptions = {\r\n looping: true,\r\n paused: false,\r\n seek: null,\r\n currentTime: 0,\r\n volume: 0,\r\n};\r\n\r\nconst useOption = <T>(value: Animated<T>) => {\r\n \"worklet\";\r\n // TODO: only create defaultValue is needed (via makeMutable)\r\n const defaultValue = Rea.useSharedValue(\r\n Rea.isSharedValue(value) ? value.value : value\r\n );\r\n return Rea.isSharedValue(value) ? value : defaultValue;\r\n};\r\n\r\nconst disposeVideo = (video: Video | null) => {\r\n \"worklet\";\r\n\r\n video?.dispose();\r\n};\r\n\r\nexport const useVideo = (\r\n source: string | null,\r\n userOptions?: Partial<PlaybackOptions>\r\n) => {\r\n const video = useVideoLoading(source);\r\n const isPaused = useOption(userOptions?.paused ?? defaultOptions.paused);\r\n const looping = useOption(userOptions?.looping ?? defaultOptions.looping);\r\n const seek = useOption(userOptions?.seek ?? defaultOptions.seek);\r\n const volume = useOption(userOptions?.volume ?? defaultOptions.volume);\r\n const currentFrame = Rea.useSharedValue<null | SkImage>(null);\r\n const currentTime = Rea.useSharedValue(0);\r\n const lastTimestamp = Rea.useSharedValue(-1);\r\n const duration = useMemo(() => video?.duration() ?? 0, [video]);\r\n const framerate = useMemo(\r\n () => (Platform.OS === \"web\" ? -1 : video?.framerate() ?? 0),\r\n [video]\r\n );\r\n const size = useMemo(() => video?.size() ?? { width: 0, height: 0 }, [video]);\r\n const rotation = useMemo(() => video?.rotation() ?? 0, [video]);\r\n const frameDuration = 1000 / framerate;\r\n const currentFrameDuration = Math.floor(frameDuration);\r\n Rea.useAnimatedReaction(\r\n () => isPaused.value,\r\n (paused) => {\r\n if (paused) {\r\n video?.pause();\r\n } else {\r\n lastTimestamp.value = -1;\r\n video?.play();\r\n }\r\n }\r\n );\r\n Rea.useAnimatedReaction(\r\n () => seek.value,\r\n (value) => {\r\n if (value !== null) {\r\n video?.seek(value);\r\n currentTime.value = value;\r\n seek.value = null;\r\n }\r\n }\r\n );\r\n Rea.useAnimatedReaction(\r\n () => volume.value,\r\n (value) => {\r\n video?.setVolume(value);\r\n }\r\n );\r\n\r\n Rea.useFrameCallback(async (frameInfo: FrameInfo) => {\r\n \"worklet\";\r\n if (!video) {\r\n return;\r\n }\r\n if (isPaused.value) {\r\n return;\r\n }\r\n const currentTimestamp = frameInfo.timestamp;\r\n if (lastTimestamp.value === -1) {\r\n lastTimestamp.value = currentTimestamp;\r\n }\r\n const delta = currentTimestamp - lastTimestamp.value;\r\n const isOver = currentTime.value + delta > duration;\r\n\r\n if (isOver && looping.value) {\r\n console.log(\"in if seek\");\r\n seek.value = 0;\r\n currentTime.value = seek.value;\r\n lastTimestamp.value = currentTimestamp;\r\n }\r\n // On Web the framerate is uknown.\r\n // This could be optimized by using requestVideoFrameCallback (Chrome only)\r\n\r\n if (\r\n (delta > currentFrameDuration * 3 && !isOver) ||\r\n Platform.OS === \"web\"\r\n ) {\r\n //console.log(`当前时间:${currentTime.value},时间间隔:${delta},当前帧持续时间:${currentFrameDuration}`)\r\n setFrame(video, currentFrame);\r\n currentTime.value += delta;\r\n lastTimestamp.value = currentTimestamp;\r\n }\r\n });\r\n\r\n useEffect(() => {\r\n return () => {\r\n // TODO: should video simply be a shared value instead?\r\n Rea.runOnUI(disposeVideo)(video);\r\n };\r\n }, [video]);\r\n\r\n return {\r\n currentFrame,\r\n currentTime,\r\n duration,\r\n framerate,\r\n rotation,\r\n size,\r\n };\r\n};\r\n"],"mappings":"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","ignoreList":[]}
|
package/lib/commonjs/index.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
var _exportNames = {
|
|
7
|
-
JsiSkImage: true
|
|
8
|
-
};
|
|
9
|
-
Object.defineProperty(exports, "JsiSkImage", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: function () {
|
|
12
|
-
return _reactNativeSkia.JsiSkImage;
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
require("@shopify/react-native-skia/src/skia/NativeSetup");
|
|
16
|
-
var _reactNativeSkia = require("@shopify/react-native-skia");
|
|
17
|
-
Object.keys(_reactNativeSkia).forEach(function (key) {
|
|
18
|
-
if (key === "default" || key === "__esModule") return;
|
|
19
|
-
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
20
|
-
if (key in exports && exports[key] === _reactNativeSkia[key]) return;
|
|
21
|
-
Object.defineProperty(exports, key, {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
get: function () {
|
|
24
|
-
return _reactNativeSkia[key];
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["require","_reactNativeSkia","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get"],"sources":["index.ts"],"sourcesContent":["import \"@shopify/react-native-skia/src/skia/NativeSetup\";\r\nexport { JsiSkImage } from \"@shopify/react-native-skia\";\r\nexport * from \"@shopify/react-native-skia\";\r\n"],"mappings":";;;;;;;;;;;;;;AAAAA,OAAA;AACA,IAAAC,gBAAA,GAAAD,OAAA;AACAE,MAAA,CAAAC,IAAA,CAAAF,gBAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,gBAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,gBAAA,CAAAI,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}
|