docs: write down the camera port and the live-view plan
CAMERA_PORT_ANDROID.md lists only what the web build has that Android does not, one row per gap, with the web file to read next to the Android one. The plan alongside it is the sketch for a live camera with a Skia filter on the frame thread.
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
# Kế hoạch: Real-time Skia filter trên camera live view dùng vision-camera v4
|
||||
|
||||
## Vấn đề
|
||||
`expo-camera` render camera preview lên native surface (PreviewView/SurfaceView) không thể intercept bằng Skia. Periodic capture bị từ chối vì mất live view.
|
||||
|
||||
## Giải pháp
|
||||
Dùng `react-native-vision-camera@4.7.3` với `useSkiaFrameProcessor` — frame processor chạy native thread, mỗi frame camera được vẽ qua Skia với ColorMatrix trước khi hiển thị.
|
||||
|
||||
## Các bước thực hiện
|
||||
|
||||
### Bước 1: Cài react-native-vision-camera@4.7.3
|
||||
```bash
|
||||
npm install react-native-vision-camera@4.7.3
|
||||
```
|
||||
- v4.7.3 là latest v4, có export `useSkiaFrameProcessor` và `frameProcessor` prop trên `Camera`
|
||||
- v5+ đã xoá Skia integration, không dùng được
|
||||
|
||||
### Bước 2: Thêm Expo Config Plugin
|
||||
Sửa `app.json`:
|
||||
- Thay `expo-camera` plugin bằng `react-native-vision-camera` plugin (v4 có plugin riêng)
|
||||
- Thêm `withEnableFrameProcessorsAndroid` để bật frame processor trên Android
|
||||
```json
|
||||
"plugins": [
|
||||
"react-native-vision-camera",
|
||||
[
|
||||
"expo-camera",
|
||||
{
|
||||
"cameraPermission": "..."
|
||||
}
|
||||
]
|
||||
]
|
||||
```
|
||||
Cần kiểm tra: v4 có expo plugin riêng (`withVisionCamera`) hay dùng thẳng tên package.
|
||||
|
||||
### Bước 3: Cập nhật App.tsx
|
||||
- Import `useCameraPermission` từ `react-native-vision-camera` thay vì `useCameraPermissions` từ `expo-camera`
|
||||
- Props: `hasPermission`, `requestPermission`
|
||||
|
||||
### Bước 4: Viết lại Viewfinder.tsx
|
||||
Component mới dùng:
|
||||
- `Camera` từ vision-camera với prop `frameProcessor={frameProcessor}`
|
||||
- `useSkiaFrameProcessor` hook — worklet chạy native, mỗi frame:
|
||||
1. Tạo `Skia.Paint()` với `Skia.ColorFilter.MakeMatrix(colorMatrix)`
|
||||
2. Gọi `frame.render(paint)` — vẽ frame qua color filter
|
||||
- `colorMatrix` là `SharedValue` từ react-native-reanimated (để worklet đọc được)
|
||||
- Grain noise, frame border, GPS watermark: giữ nguyên overlay React Native / Skia Canvas trên top
|
||||
|
||||
```tsx
|
||||
const App = () => {
|
||||
const frameProcessor = useSkiaFrameProcessor((frame) => {
|
||||
'worklet';
|
||||
const paint = Skia.Paint();
|
||||
paint.setColorFilter(Skia.ColorFilter.MakeMatrix(colorMatrixSV.value));
|
||||
frame.render(paint);
|
||||
}, [colorMatrixSV]);
|
||||
|
||||
return (
|
||||
<Camera
|
||||
style={StyleSheet.absoluteFill}
|
||||
device={device}
|
||||
isActive={true}
|
||||
frameProcessor={frameProcessor}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Bước 5: Loại bỏ expo-camera khỏi code
|
||||
- `CameraView` → `Camera` (vision-camera)
|
||||
- Xoá imports không dùng
|
||||
- Giữ `expo-camera` trong package.json (không gỡ, tránh lỗi autolinking)
|
||||
|
||||
### Bước 6: Re-prebuild & build APK
|
||||
```bash
|
||||
rm -rf android
|
||||
npx expo prebuild --platform android
|
||||
echo "sdk.dir=/home/locpham/android-sdk" > android/local.properties
|
||||
cd android && ./gradlew assembleDebug
|
||||
```
|
||||
(Không chạy `clean` — tránh lỗi CMake codegen paths)
|
||||
|
||||
## API đã xác nhận (v4.7.3)
|
||||
| Export | Path |
|
||||
|---|---|
|
||||
| `Camera` | `react-native-vision-camera` |
|
||||
| `useCameraDevice` | `react-native-vision-camera` |
|
||||
| `useCameraPermission` | `react-native-vision-camera` |
|
||||
| `useSkiaFrameProcessor` | `react-native-vision-camera` |
|
||||
| `SkiaCameraCanvas` | `react-native-vision-camera` |
|
||||
| Expo plugin (`withVisionCamera`) | `lib/module/expo-plugin/withVisionCamera` |
|
||||
|
||||
## Rủi ro & Xử lý
|
||||
| Rủi ro | Xử lý |
|
||||
|---|---|
|
||||
| `react-native-worklets-core` conflict | Đã có sẵn qua `react-native-reanimated` dependency |
|
||||
| CameraX dependency (`NoClassDefFoundError`) | v4 dùng `CameraX` không phải Nitro — build an toàn hơn v5 |
|
||||
| CMake codegen paths lỗi sau `clean` | Không dùng `./gradlew clean`, dùng `--rerun-tasks` nếu cần |
|
||||
| Frame processor không chạy trên Android | Bật flag qua Expo plugin: `withEnableFrameProcessorsAndroid` |
|
||||
|
||||
## Kiểm thử
|
||||
1. Build APK thành công
|
||||
2. Camera live view hiển thị với filter:
|
||||
- B&W/monochrome → true grayscale
|
||||
- Saturation, temp, tint, exposure thay đổi real-time
|
||||
3. Grain noise, frame border, GPS watermark vẫn hoạt động
|
||||
4. Library mode không bị ảnh hưởng
|
||||
Reference in New Issue
Block a user