@movementinfra/expo-twostep-video 0.1.0
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 +21 -0
- package/README.md +420 -0
- package/build/ExpoTwostepVideo.types.d.ts +65 -0
- package/build/ExpoTwostepVideo.types.d.ts.map +1 -0
- package/build/ExpoTwostepVideo.types.js +2 -0
- package/build/ExpoTwostepVideo.types.js.map +1 -0
- package/build/ExpoTwostepVideoModule.d.ts +70 -0
- package/build/ExpoTwostepVideoModule.d.ts.map +1 -0
- package/build/ExpoTwostepVideoModule.js +5 -0
- package/build/ExpoTwostepVideoModule.js.map +1 -0
- package/build/ExpoTwostepVideoModule.web.d.ts +14 -0
- package/build/ExpoTwostepVideoModule.web.d.ts.map +1 -0
- package/build/ExpoTwostepVideoModule.web.js +12 -0
- package/build/ExpoTwostepVideoModule.web.js.map +1 -0
- package/build/ExpoTwostepVideoView.d.ts +27 -0
- package/build/ExpoTwostepVideoView.d.ts.map +1 -0
- package/build/ExpoTwostepVideoView.js +47 -0
- package/build/ExpoTwostepVideoView.js.map +1 -0
- package/build/ExpoTwostepVideoView.web.d.ts +4 -0
- package/build/ExpoTwostepVideoView.web.d.ts.map +1 -0
- package/build/ExpoTwostepVideoView.web.js +8 -0
- package/build/ExpoTwostepVideoView.web.js.map +1 -0
- package/build/index.d.ts +569 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +430 -0
- package/build/index.js.map +1 -0
- package/expo-module.config.json +10 -0
- package/ios/ExpoTwostepVideo.podspec +30 -0
- package/ios/ExpoTwostepVideoModule.swift +739 -0
- package/ios/ExpoTwostepVideoView.swift +223 -0
- package/ios/Package.swift +32 -0
- package/ios/TwoStepVideo/Core/AssetLoader.swift +175 -0
- package/ios/TwoStepVideo/Core/VideoExporter.swift +353 -0
- package/ios/TwoStepVideo/Core/VideoTransformer.swift +365 -0
- package/ios/TwoStepVideo/Core/VideoTrimmer.swift +300 -0
- package/ios/TwoStepVideo/Models/ExportConfiguration.swift +104 -0
- package/ios/TwoStepVideo/Models/LoopConfiguration.swift +101 -0
- package/ios/TwoStepVideo/Models/TimeRange.swift +98 -0
- package/ios/TwoStepVideo/Models/VideoAsset.swift +126 -0
- package/ios/TwoStepVideo/Models/VideoEditingError.swift +82 -0
- package/ios/TwoStepVideo/TwoStepVideo.swift +30 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Richard Guo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
# expo-twostep-video
|
|
2
|
+
|
|
3
|
+
Professional video editing for React Native, powered by native AVFoundation.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/expo-twostep-video)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- ๐ฌ **Load videos** from file system or Photos library
|
|
11
|
+
- โ๏ธ **Trim videos** with frame-accurate precision
|
|
12
|
+
- ๐๏ธ **Create multi-segment compositions** (highlight reels)
|
|
13
|
+
- ๐ธ **Generate thumbnails** at any timestamp
|
|
14
|
+
- ๐พ **Export** with customizable quality settings
|
|
15
|
+
- ๐ **Real-time progress tracking** during exports
|
|
16
|
+
- ๐งน **Automatic cleanup** of partial/temp files
|
|
17
|
+
- ๐ **Type-safe TypeScript API** with full IntelliSense
|
|
18
|
+
- ๐ฑ **iOS 15+** support
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx expo install expo-twostep-video
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import * as TwoStepVideo from 'expo-twostep-video';
|
|
30
|
+
|
|
31
|
+
// Load a video
|
|
32
|
+
const asset = await TwoStepVideo.loadAsset({
|
|
33
|
+
uri: 'file:///path/to/video.mp4'
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Trim it (5 seconds to 15 seconds)
|
|
37
|
+
const composition = await TwoStepVideo.trimVideo({
|
|
38
|
+
assetId: asset.id,
|
|
39
|
+
startTime: 5.0,
|
|
40
|
+
endTime: 15.0
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Export with progress tracking
|
|
44
|
+
const result = await TwoStepVideo.exportVideo({
|
|
45
|
+
compositionId: composition.id,
|
|
46
|
+
quality: TwoStepVideo.Quality.HIGH
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
console.log('Exported to:', result.uri);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Complete Example
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import React, { useState, useEffect } from 'react';
|
|
56
|
+
import { View, Button, Text } from 'react-native';
|
|
57
|
+
import * as TwoStepVideo from 'expo-twostep-video';
|
|
58
|
+
|
|
59
|
+
function VideoEditor() {
|
|
60
|
+
const [progress, setProgress] = useState(0);
|
|
61
|
+
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
const subscription = TwoStepVideo.addExportProgressListener((event) => {
|
|
64
|
+
setProgress(event.progress);
|
|
65
|
+
});
|
|
66
|
+
return () => subscription.remove();
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
const trimAndExport = async () => {
|
|
70
|
+
try {
|
|
71
|
+
// Load
|
|
72
|
+
const asset = await TwoStepVideo.loadAsset({
|
|
73
|
+
uri: 'file:///path/to/video.mp4'
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Trim
|
|
77
|
+
const composition = await TwoStepVideo.trimVideo({
|
|
78
|
+
assetId: asset.id,
|
|
79
|
+
startTime: 0,
|
|
80
|
+
endTime: 10
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Export
|
|
84
|
+
const result = await TwoStepVideo.exportVideo({
|
|
85
|
+
compositionId: composition.id,
|
|
86
|
+
quality: TwoStepVideo.Quality.HIGH
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
alert(`Saved to: ${result.uri}`);
|
|
90
|
+
|
|
91
|
+
// Cleanup
|
|
92
|
+
TwoStepVideo.releaseAsset(asset.id);
|
|
93
|
+
TwoStepVideo.releaseComposition(composition.id);
|
|
94
|
+
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error('Error:', error);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<View>
|
|
102
|
+
<Text>Progress: {Math.round(progress * 100)}%</Text>
|
|
103
|
+
<Button title="Trim & Export" onPress={trimAndExport} />
|
|
104
|
+
</View>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## API Reference
|
|
110
|
+
|
|
111
|
+
### Loading Videos
|
|
112
|
+
|
|
113
|
+
#### `loadAsset(options)`
|
|
114
|
+
Load a video from a file URI.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const asset = await TwoStepVideo.loadAsset({
|
|
118
|
+
uri: 'file:///path/to/video.mp4'
|
|
119
|
+
});
|
|
120
|
+
// Returns: { id, duration, width, height, frameRate, hasAudio }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### `loadAssetFromPhotos(localIdentifier)`
|
|
124
|
+
Load a video from the Photos library.
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const asset = await TwoStepVideo.loadAssetFromPhotos(photoAsset.id);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### `validateVideoUri(uri)`
|
|
131
|
+
Quickly validate a video URI without loading.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
const isValid = await TwoStepVideo.validateVideoUri(uri);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Trimming
|
|
138
|
+
|
|
139
|
+
#### `trimVideo(options)`
|
|
140
|
+
Trim to a single time range.
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
const composition = await TwoStepVideo.trimVideo({
|
|
144
|
+
assetId: asset.id,
|
|
145
|
+
startTime: 5.0, // seconds
|
|
146
|
+
endTime: 15.0
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### `trimVideoMultiple(options)`
|
|
151
|
+
Create a composition from multiple segments.
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const composition = await TwoStepVideo.trimVideoMultiple({
|
|
155
|
+
assetId: asset.id,
|
|
156
|
+
segments: [
|
|
157
|
+
{ start: 0, end: 5 },
|
|
158
|
+
{ start: 10, end: 15 },
|
|
159
|
+
{ start: 20, end: 25 }
|
|
160
|
+
]
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Thumbnails
|
|
165
|
+
|
|
166
|
+
#### `generateThumbnails(options)`
|
|
167
|
+
Extract thumbnail images at specific times.
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
const thumbnails = await TwoStepVideo.generateThumbnails({
|
|
171
|
+
assetId: asset.id,
|
|
172
|
+
times: [0, 5, 10, 15],
|
|
173
|
+
size: { width: 300, height: 300 }
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Use in Image component
|
|
177
|
+
<Image source={{ uri: `data:image/png;base64,${thumbnails[0]}` }} />
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Exporting
|
|
181
|
+
|
|
182
|
+
#### `exportVideo(options)`
|
|
183
|
+
Export a composition to a file.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
const result = await TwoStepVideo.exportVideo({
|
|
187
|
+
compositionId: composition.id,
|
|
188
|
+
quality: TwoStepVideo.Quality.HIGH, // or LOW, MEDIUM, HIGHEST
|
|
189
|
+
outputUri: 'file:///path/to/output.mp4' // optional
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
#### `exportAsset(options)`
|
|
194
|
+
Export an asset directly (without trimming).
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
const result = await TwoStepVideo.exportAsset({
|
|
198
|
+
assetId: asset.id,
|
|
199
|
+
quality: TwoStepVideo.Quality.MEDIUM
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Events
|
|
204
|
+
|
|
205
|
+
#### `addExportProgressListener(callback)`
|
|
206
|
+
Listen for export progress updates.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const subscription = TwoStepVideo.addExportProgressListener((event) => {
|
|
210
|
+
console.log(`${Math.round(event.progress * 100)}%`);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Remove listener
|
|
214
|
+
subscription.remove();
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Memory Management
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
// Release assets when done
|
|
221
|
+
TwoStepVideo.releaseAsset(asset.id);
|
|
222
|
+
TwoStepVideo.releaseComposition(composition.id);
|
|
223
|
+
|
|
224
|
+
// Release all at once
|
|
225
|
+
TwoStepVideo.releaseAll();
|
|
226
|
+
|
|
227
|
+
// Clean up temp files
|
|
228
|
+
TwoStepVideo.cleanupFile(tempFileUri);
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Quality Presets
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
TwoStepVideo.Quality.LOW // ~0.1 bits per pixel
|
|
235
|
+
TwoStepVideo.Quality.MEDIUM // ~0.2 bits per pixel
|
|
236
|
+
TwoStepVideo.Quality.HIGH // ~0.4 bits per pixel (recommended)
|
|
237
|
+
TwoStepVideo.Quality.HIGHEST // ~0.8 bits per pixel
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## TypeScript Support
|
|
241
|
+
|
|
242
|
+
Full TypeScript definitions included:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
interface VideoAsset {
|
|
246
|
+
id: string;
|
|
247
|
+
duration: number;
|
|
248
|
+
width: number;
|
|
249
|
+
height: number;
|
|
250
|
+
frameRate: number;
|
|
251
|
+
hasAudio: boolean;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
interface VideoComposition {
|
|
255
|
+
id: string;
|
|
256
|
+
duration: number;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
interface ExportResult {
|
|
260
|
+
uri: string;
|
|
261
|
+
path: string;
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Advanced Usage
|
|
266
|
+
|
|
267
|
+
### Create a Highlight Reel
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
async function createHighlightReel(videoUri: string) {
|
|
271
|
+
const asset = await TwoStepVideo.loadAsset({ uri: videoUri });
|
|
272
|
+
|
|
273
|
+
// Extract 3-second clips evenly throughout video
|
|
274
|
+
const numClips = 5;
|
|
275
|
+
const interval = asset.duration / (numClips + 1);
|
|
276
|
+
|
|
277
|
+
const segments = Array.from({ length: numClips }, (_, i) => ({
|
|
278
|
+
start: interval * (i + 1),
|
|
279
|
+
end: Math.min(interval * (i + 1) + 3, asset.duration)
|
|
280
|
+
}));
|
|
281
|
+
|
|
282
|
+
const composition = await TwoStepVideo.trimVideoMultiple({
|
|
283
|
+
assetId: asset.id,
|
|
284
|
+
segments
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
return await TwoStepVideo.exportVideo({
|
|
288
|
+
compositionId: composition.id,
|
|
289
|
+
quality: TwoStepVideo.Quality.HIGH
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### With Progress Bar
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
function VideoExporter({ videoUri }) {
|
|
298
|
+
const progress = TwoStepVideo.useExportProgress();
|
|
299
|
+
|
|
300
|
+
return (
|
|
301
|
+
<View>
|
|
302
|
+
<ProgressBar progress={progress} />
|
|
303
|
+
<Text>{Math.round(progress * 100)}%</Text>
|
|
304
|
+
</View>
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Development
|
|
310
|
+
|
|
311
|
+
This module contains both the Swift library and Expo bridge in one package.
|
|
312
|
+
|
|
313
|
+
### Running Tests
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
# Run Swift unit tests
|
|
317
|
+
npm run test:swift
|
|
318
|
+
|
|
319
|
+
# All tests should pass:
|
|
320
|
+
# โ
69 tests executed, 20 skipped (integration tests)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Building
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
# Build TypeScript
|
|
327
|
+
npm run build
|
|
328
|
+
|
|
329
|
+
# Clean build artifacts
|
|
330
|
+
npm run clean
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Running Example App
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
cd example
|
|
337
|
+
npm install
|
|
338
|
+
npm run ios
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Architecture
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
expo-twostep-video/
|
|
345
|
+
โโโ ios/
|
|
346
|
+
โ โโโ TwoStepVideo/ # Swift library
|
|
347
|
+
โ โ โโโ Models/ # Data models
|
|
348
|
+
โ โ โโโ Core/ # Core functionality
|
|
349
|
+
โ โ โโโ TwoStepVideo.swift # Main facade
|
|
350
|
+
โ โโโ Tests/ # Swift unit tests
|
|
351
|
+
โ โโโ ExpoTwoStepVideoModule.swift # Expo bridge
|
|
352
|
+
โ โโโ Package.swift # Swift package for testing
|
|
353
|
+
โโโ src/
|
|
354
|
+
โ โโโ index.ts # TypeScript API
|
|
355
|
+
โโโ example/ # Example React Native app
|
|
356
|
+
โโโ docs/ # Documentation
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Documentation
|
|
360
|
+
|
|
361
|
+
- [Architecture](./docs/ARCHITECTURE.md) - Design and implementation details
|
|
362
|
+
- [Developer Guide](./docs/CLAUDE.md) - Best practices and patterns
|
|
363
|
+
- [Temp File Management](./docs/TEMP_FILE_MANAGEMENT.md) - File cleanup strategies
|
|
364
|
+
|
|
365
|
+
## Requirements
|
|
366
|
+
|
|
367
|
+
- iOS 15.0+
|
|
368
|
+
- Expo SDK 50+
|
|
369
|
+
- React Native 0.72+
|
|
370
|
+
|
|
371
|
+
## Platform Support
|
|
372
|
+
|
|
373
|
+
- โ
iOS (fully supported)
|
|
374
|
+
- โณ Android (coming soon)
|
|
375
|
+
|
|
376
|
+
## Error Handling
|
|
377
|
+
|
|
378
|
+
All errors include descriptive codes and messages:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
try {
|
|
382
|
+
await TwoStepVideo.exportVideo(options);
|
|
383
|
+
} catch (error: any) {
|
|
384
|
+
switch (error.code) {
|
|
385
|
+
case 'EXPORT_FAILED':
|
|
386
|
+
// Handle export failure
|
|
387
|
+
break;
|
|
388
|
+
case 'ASSET_NOT_FOUND':
|
|
389
|
+
// Asset was released too early
|
|
390
|
+
break;
|
|
391
|
+
default:
|
|
392
|
+
console.error('Unknown error:', error);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## Performance Tips
|
|
398
|
+
|
|
399
|
+
1. **Release resources promptly** after use
|
|
400
|
+
2. **Use `releaseAll()`** when unmounting components
|
|
401
|
+
3. **Validate URIs** before loading with `validateVideoUri()`
|
|
402
|
+
4. **Clean up temp files** after moving/uploading
|
|
403
|
+
|
|
404
|
+
## Contributing
|
|
405
|
+
|
|
406
|
+
Contributions welcome! Please see [CONTRIBUTING](./docs/CONTRIBUTING.md).
|
|
407
|
+
|
|
408
|
+
## License
|
|
409
|
+
|
|
410
|
+
MIT ยฉ Richard Guo
|
|
411
|
+
|
|
412
|
+
## Support
|
|
413
|
+
|
|
414
|
+
- ๐ง Email: richardg7890@gmail.com
|
|
415
|
+
- ๐ Issues: [GitHub Issues](https://github.com/rguo123/twostep-video/issues)
|
|
416
|
+
- ๐ Docs: [Full Documentation](./docs/)
|
|
417
|
+
|
|
418
|
+
## Acknowledgments
|
|
419
|
+
|
|
420
|
+
Built with AVFoundation and Expo Modules.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
/**
|
|
3
|
+
* Playback status event payload
|
|
4
|
+
*/
|
|
5
|
+
export type PlaybackStatusEvent = {
|
|
6
|
+
status: 'ready' | 'playing' | 'paused' | 'ended' | 'seeked';
|
|
7
|
+
time?: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Progress event payload
|
|
11
|
+
*/
|
|
12
|
+
export type ProgressEvent = {
|
|
13
|
+
currentTime: number;
|
|
14
|
+
duration: number;
|
|
15
|
+
progress: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Error event payload
|
|
19
|
+
*/
|
|
20
|
+
export type ErrorEvent = {
|
|
21
|
+
error: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Video player view props
|
|
25
|
+
*/
|
|
26
|
+
export type TwoStepVideoViewProps = {
|
|
27
|
+
/** ID of a composition to play (from trimVideo, mirrorVideo, etc.) */
|
|
28
|
+
compositionId?: string;
|
|
29
|
+
/** ID of an asset to play (from loadAsset) */
|
|
30
|
+
assetId?: string;
|
|
31
|
+
/** Enable continuous looping - video will restart automatically when it ends */
|
|
32
|
+
loop?: boolean;
|
|
33
|
+
/** Called when playback status changes */
|
|
34
|
+
onPlaybackStatusChange?: (event: {
|
|
35
|
+
nativeEvent: PlaybackStatusEvent;
|
|
36
|
+
}) => void;
|
|
37
|
+
/** Called periodically with playback progress */
|
|
38
|
+
onProgress?: (event: {
|
|
39
|
+
nativeEvent: ProgressEvent;
|
|
40
|
+
}) => void;
|
|
41
|
+
/** Called when playback reaches the end (not called if loop is true) */
|
|
42
|
+
onEnd?: (event: {
|
|
43
|
+
nativeEvent: Record<string, never>;
|
|
44
|
+
}) => void;
|
|
45
|
+
/** Called when an error occurs */
|
|
46
|
+
onError?: (event: {
|
|
47
|
+
nativeEvent: ErrorEvent;
|
|
48
|
+
}) => void;
|
|
49
|
+
/** View style */
|
|
50
|
+
style?: StyleProp<ViewStyle>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Ref handle for video player view
|
|
54
|
+
*/
|
|
55
|
+
export type TwoStepVideoViewRef = {
|
|
56
|
+
/** Start playback */
|
|
57
|
+
play: () => Promise<void>;
|
|
58
|
+
/** Pause playback */
|
|
59
|
+
pause: () => Promise<void>;
|
|
60
|
+
/** Seek to a specific time in seconds */
|
|
61
|
+
seek: (time: number) => Promise<void>;
|
|
62
|
+
/** Restart playback from the beginning */
|
|
63
|
+
replay: () => Promise<void>;
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=ExpoTwostepVideo.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoTwostepVideo.types.d.ts","sourceRoot":"","sources":["../src/ExpoTwostepVideo.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0CAA0C;IAC1C,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,mBAAmB,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/E,iDAAiD;IACjD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,aAAa,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7D,wEAAwE;IACxE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;KAAE,KAAK,IAAI,CAAC;IAChE,kCAAkC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IACvD,iBAAiB;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,qBAAqB;IACrB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,qBAAqB;IACrB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,yCAAyC;IACzC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoTwostepVideo.types.js","sourceRoot":"","sources":["../src/ExpoTwostepVideo.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StyleProp, ViewStyle } from 'react-native';\n\n/**\n * Playback status event payload\n */\nexport type PlaybackStatusEvent = {\n status: 'ready' | 'playing' | 'paused' | 'ended' | 'seeked';\n time?: number;\n};\n\n/**\n * Progress event payload\n */\nexport type ProgressEvent = {\n currentTime: number;\n duration: number;\n progress: number;\n};\n\n/**\n * Error event payload\n */\nexport type ErrorEvent = {\n error: string;\n};\n\n/**\n * Video player view props\n */\nexport type TwoStepVideoViewProps = {\n /** ID of a composition to play (from trimVideo, mirrorVideo, etc.) */\n compositionId?: string;\n /** ID of an asset to play (from loadAsset) */\n assetId?: string;\n /** Enable continuous looping - video will restart automatically when it ends */\n loop?: boolean;\n /** Called when playback status changes */\n onPlaybackStatusChange?: (event: { nativeEvent: PlaybackStatusEvent }) => void;\n /** Called periodically with playback progress */\n onProgress?: (event: { nativeEvent: ProgressEvent }) => void;\n /** Called when playback reaches the end (not called if loop is true) */\n onEnd?: (event: { nativeEvent: Record<string, never> }) => void;\n /** Called when an error occurs */\n onError?: (event: { nativeEvent: ErrorEvent }) => void;\n /** View style */\n style?: StyleProp<ViewStyle>;\n};\n\n/**\n * Ref handle for video player view\n */\nexport type TwoStepVideoViewRef = {\n /** Start playback */\n play: () => Promise<void>;\n /** Pause playback */\n pause: () => Promise<void>;\n /** Seek to a specific time in seconds */\n seek: (time: number) => Promise<void>;\n /** Restart playback from the beginning */\n replay: () => Promise<void>;\n};\n"]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { NativeModule } from 'expo-modules-core';
|
|
2
|
+
interface TimeSegment {
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
}
|
|
6
|
+
interface ThumbnailSize {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
interface AssetResult {
|
|
11
|
+
id: string;
|
|
12
|
+
duration: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
frameRate: number;
|
|
16
|
+
hasAudio: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface CompositionResult {
|
|
19
|
+
id: string;
|
|
20
|
+
duration: number;
|
|
21
|
+
}
|
|
22
|
+
interface CompositionResultWithDuration {
|
|
23
|
+
id: string;
|
|
24
|
+
duration: number;
|
|
25
|
+
}
|
|
26
|
+
interface LoopResult {
|
|
27
|
+
id: string;
|
|
28
|
+
duration: number;
|
|
29
|
+
loopCount: number;
|
|
30
|
+
totalPlays: number;
|
|
31
|
+
}
|
|
32
|
+
interface ExportResult {
|
|
33
|
+
uri: string;
|
|
34
|
+
path: string;
|
|
35
|
+
}
|
|
36
|
+
interface ExportProgressEvent {
|
|
37
|
+
progress: number;
|
|
38
|
+
assetId?: string;
|
|
39
|
+
compositionId?: string;
|
|
40
|
+
}
|
|
41
|
+
declare class ExpoTwostepVideoModule extends NativeModule<{
|
|
42
|
+
onExportProgress: (event: ExportProgressEvent) => void;
|
|
43
|
+
}> {
|
|
44
|
+
QUALITY_LOW: string;
|
|
45
|
+
QUALITY_MEDIUM: string;
|
|
46
|
+
QUALITY_HIGH: string;
|
|
47
|
+
QUALITY_HIGHEST: string;
|
|
48
|
+
MIRROR_HORIZONTAL: string;
|
|
49
|
+
MIRROR_VERTICAL: string;
|
|
50
|
+
MIRROR_BOTH: string;
|
|
51
|
+
loadAsset(uri: string): Promise<AssetResult>;
|
|
52
|
+
loadAssetFromPhotos(localIdentifier: string): Promise<AssetResult>;
|
|
53
|
+
validateVideoUri(uri: string): Promise<boolean>;
|
|
54
|
+
trimVideo(assetId: string, startTime: number, endTime: number): Promise<CompositionResult>;
|
|
55
|
+
trimVideoMultiple(assetId: string, segments: TimeSegment[]): Promise<CompositionResult>;
|
|
56
|
+
mirrorVideo(assetId: string, axis: string, startTime?: number, endTime?: number): Promise<CompositionResult>;
|
|
57
|
+
adjustSpeed(assetId: string, speed: number, startTime?: number, endTime?: number): Promise<CompositionResult>;
|
|
58
|
+
transformVideo(assetId: string, speed?: number, mirrorAxis?: string, startTime?: number, endTime?: number): Promise<CompositionResultWithDuration>;
|
|
59
|
+
loopSegment(assetId: string, startTime: number, endTime: number, loopCount: number): Promise<LoopResult>;
|
|
60
|
+
generateThumbnails(assetId: string, times: number[], size?: ThumbnailSize): Promise<string[]>;
|
|
61
|
+
exportVideo(compositionId: string, outputUri?: string, quality?: string): Promise<ExportResult>;
|
|
62
|
+
exportAsset(assetId: string, outputUri?: string, quality?: string): Promise<ExportResult>;
|
|
63
|
+
cleanupFile(uri: string): void;
|
|
64
|
+
releaseAsset(assetId: string): void;
|
|
65
|
+
releaseComposition(compositionId: string): void;
|
|
66
|
+
releaseAll(): void;
|
|
67
|
+
}
|
|
68
|
+
declare const _default: ExpoTwostepVideoModule;
|
|
69
|
+
export default _default;
|
|
70
|
+
//# sourceMappingURL=ExpoTwostepVideoModule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoTwostepVideoModule.d.ts","sourceRoot":"","sources":["../src/ExpoTwostepVideoModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AAEtE,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,iBAAiB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,6BAA6B;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,YAAY;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,OAAO,OAAO,sBAAuB,SAAQ,YAAY,CAAC;IACxD,gBAAgB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACxD,CAAC;IAEA,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IAGpB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAC5C,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAClE,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAG/C,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAC1F,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC;IACvF,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAC5G,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAC7G,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,6BAA6B,CAAC;IAClJ,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAGxG,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAG7F,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAC/F,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAGzF,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAC9B,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IACnC,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAC/C,UAAU,IAAI,IAAI;CACnB;;AAID,wBAA+E"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
// This call loads the native module object from the JSI.
|
|
3
|
+
// The module name must match Name("ExpoTwoStepVideo") in the Swift module.
|
|
4
|
+
export default requireNativeModule('ExpoTwoStepVideo');
|
|
5
|
+
//# sourceMappingURL=ExpoTwostepVideoModule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoTwostepVideoModule.js","sourceRoot":"","sources":["../src/ExpoTwostepVideoModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAwFtE,yDAAyD;AACzD,2EAA2E;AAC3E,eAAe,mBAAmB,CAAyB,kBAAkB,CAAC,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from 'expo-modules-core';\n\ninterface TimeSegment {\n start: number;\n end: number;\n}\n\ninterface ThumbnailSize {\n width: number;\n height: number;\n}\n\ninterface AssetResult {\n id: string;\n duration: number;\n width: number;\n height: number;\n frameRate: number;\n hasAudio: boolean;\n}\n\ninterface CompositionResult {\n id: string;\n duration: number;\n}\n\ninterface CompositionResultWithDuration {\n id: string;\n duration: number;\n}\n\ninterface LoopResult {\n id: string;\n duration: number;\n loopCount: number;\n totalPlays: number;\n}\n\ninterface ExportResult {\n uri: string;\n path: string;\n}\n\ninterface ExportProgressEvent {\n progress: number;\n assetId?: string;\n compositionId?: string;\n}\n\ndeclare class ExpoTwostepVideoModule extends NativeModule<{\n onExportProgress: (event: ExportProgressEvent) => void;\n}> {\n // Constants\n QUALITY_LOW: string;\n QUALITY_MEDIUM: string;\n QUALITY_HIGH: string;\n QUALITY_HIGHEST: string;\n MIRROR_HORIZONTAL: string;\n MIRROR_VERTICAL: string;\n MIRROR_BOTH: string;\n\n // Asset loading\n loadAsset(uri: string): Promise<AssetResult>;\n loadAssetFromPhotos(localIdentifier: string): Promise<AssetResult>;\n validateVideoUri(uri: string): Promise<boolean>;\n\n // Editing operations\n trimVideo(assetId: string, startTime: number, endTime: number): Promise<CompositionResult>;\n trimVideoMultiple(assetId: string, segments: TimeSegment[]): Promise<CompositionResult>;\n mirrorVideo(assetId: string, axis: string, startTime?: number, endTime?: number): Promise<CompositionResult>;\n adjustSpeed(assetId: string, speed: number, startTime?: number, endTime?: number): Promise<CompositionResult>;\n transformVideo(assetId: string, speed?: number, mirrorAxis?: string, startTime?: number, endTime?: number): Promise<CompositionResultWithDuration>;\n loopSegment(assetId: string, startTime: number, endTime: number, loopCount: number): Promise<LoopResult>;\n\n // Thumbnails\n generateThumbnails(assetId: string, times: number[], size?: ThumbnailSize): Promise<string[]>;\n\n // Export\n exportVideo(compositionId: string, outputUri?: string, quality?: string): Promise<ExportResult>;\n exportAsset(assetId: string, outputUri?: string, quality?: string): Promise<ExportResult>;\n\n // Cleanup\n cleanupFile(uri: string): void;\n releaseAsset(assetId: string): void;\n releaseComposition(compositionId: string): void;\n releaseAll(): void;\n}\n\n// This call loads the native module object from the JSI.\n// The module name must match Name(\"ExpoTwoStepVideo\") in the Swift module.\nexport default requireNativeModule<ExpoTwostepVideoModule>('ExpoTwoStepVideo');\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
QUALITY_LOW: string;
|
|
3
|
+
QUALITY_MEDIUM: string;
|
|
4
|
+
QUALITY_HIGH: string;
|
|
5
|
+
QUALITY_HIGHEST: string;
|
|
6
|
+
MIRROR_HORIZONTAL: string;
|
|
7
|
+
MIRROR_VERTICAL: string;
|
|
8
|
+
MIRROR_BOTH: string;
|
|
9
|
+
addListener: () => {
|
|
10
|
+
remove: () => void;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export default _default;
|
|
14
|
+
//# sourceMappingURL=ExpoTwostepVideoModule.web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoTwostepVideoModule.web.d.ts","sourceRoot":"","sources":["../src/ExpoTwostepVideoModule.web.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,wBASE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Web is not supported - this is a stub
|
|
2
|
+
export default {
|
|
3
|
+
QUALITY_LOW: 'low',
|
|
4
|
+
QUALITY_MEDIUM: 'medium',
|
|
5
|
+
QUALITY_HIGH: 'high',
|
|
6
|
+
QUALITY_HIGHEST: 'highest',
|
|
7
|
+
MIRROR_HORIZONTAL: 'horizontal',
|
|
8
|
+
MIRROR_VERTICAL: 'vertical',
|
|
9
|
+
MIRROR_BOTH: 'both',
|
|
10
|
+
addListener: () => ({ remove: () => { } }),
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=ExpoTwostepVideoModule.web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoTwostepVideoModule.web.js","sourceRoot":"","sources":["../src/ExpoTwostepVideoModule.web.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,eAAe;IACb,WAAW,EAAE,KAAK;IAClB,cAAc,EAAE,QAAQ;IACxB,YAAY,EAAE,MAAM;IACpB,eAAe,EAAE,SAAS;IAC1B,iBAAiB,EAAE,YAAY;IAC/B,eAAe,EAAE,UAAU;IAC3B,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;CAC1C,CAAC","sourcesContent":["// Web is not supported - this is a stub\nexport default {\n QUALITY_LOW: 'low',\n QUALITY_MEDIUM: 'medium',\n QUALITY_HIGH: 'high',\n QUALITY_HIGHEST: 'highest',\n MIRROR_HORIZONTAL: 'horizontal',\n MIRROR_VERTICAL: 'vertical',\n MIRROR_BOTH: 'both',\n addListener: () => ({ remove: () => {} }),\n};\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { TwoStepVideoViewProps, TwoStepVideoViewRef } from './ExpoTwostepVideo.types';
|
|
3
|
+
/**
|
|
4
|
+
* Video player view that can play compositions and assets directly
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* const playerRef = useRef<TwoStepVideoViewRef>(null);
|
|
9
|
+
*
|
|
10
|
+
* // Play a composition (from mirrorVideo, trimVideo, etc.)
|
|
11
|
+
* <TwoStepVideoView
|
|
12
|
+
* ref={playerRef}
|
|
13
|
+
* compositionId={composition.id}
|
|
14
|
+
* onPlaybackStatusChange={(e) => console.log(e.nativeEvent.status)}
|
|
15
|
+
* onProgress={(e) => setProgress(e.nativeEvent.progress)}
|
|
16
|
+
* style={{ width: '100%', height: 300 }}
|
|
17
|
+
* />
|
|
18
|
+
*
|
|
19
|
+
* // Control playback
|
|
20
|
+
* playerRef.current?.play();
|
|
21
|
+
* playerRef.current?.pause();
|
|
22
|
+
* playerRef.current?.seek(5.0);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare const TwoStepVideoView: React.ForwardRefExoticComponent<TwoStepVideoViewProps & React.RefAttributes<TwoStepVideoViewRef>>;
|
|
26
|
+
export default TwoStepVideoView;
|
|
27
|
+
//# sourceMappingURL=ExpoTwostepVideoView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoTwostepVideoView.d.ts","sourceRoot":"","sources":["../src/ExpoTwostepVideoView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAiBtF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,QAAA,MAAM,gBAAgB,mGAqBrB,CAAC;AAIF,eAAe,gBAAgB,CAAC"}
|