Skip to content

Commit cc58a67

Browse files
felireFelipe Rodriguez Esturofrodriguez-humrousavy
authored
feat: Add onBytesWrittenVideo event while recording Videos (#3549)
* Android Event Emitter for receiving Bytes when recording Video * Implement Android Event Emitter as it should be for Android Views * working for ios * update docs * small changes * fix lint issues * fix pr comments * chore: Format Swift code --------- Co-authored-by: Felipe Rodriguez Esturo <[email protected]> Co-authored-by: Felipe Rodriguez Esturo <[email protected]> Co-authored-by: Marc Rousavy <[email protected]>
1 parent 130cbab commit cc58a67

25 files changed

+110
-18
lines changed

docs/docs/guides/RECORDING_VIDEOS.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ To start a video recording you first have to enable video capture:
4242
{...props}
4343
video={true}
4444
audio={true} // <-- optional
45+
onBytesWrittenVideo={(bytes) => {/*Whatever you need with bytes in realtime while it is recording*/}} // <-- optional
4546
/>
4647
```
4748

example/src/CameraPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ export function CameraPage({ navigation }: Props): React.ReactElement {
205205
ref={camera}
206206
onInitialized={onInitialized}
207207
onError={onError}
208+
onBytesWrittenVideo={(bytes) => console.log(`Bytes written: ${bytes / 1024 / 1024} MB!`)}
208209
onStarted={() => console.log('Camera started!')}
209210
onStopped={() => console.log('Camera stopped!')}
210211
onPreviewStarted={() => console.log('Preview started!')}

package/android/src/main/cpp/frameprocessors/FrameHostObject.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ std::vector<jsi::PropNameID> FrameHostObject::getPropertyNames(jsi::Runtime& rt)
5555
return result;
5656
}
5757

58-
#define JSI_FUNC [=](jsi::Runtime & runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value
58+
#define JSI_FUNC [=](jsi::Runtime & runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count)->jsi::Value
5959

6060
jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) {
6161
auto name = propName.utf8(runtime);

package/android/src/main/java/com/mrousavy/camera/core/CameraSession+Video.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ fun CameraSession.startRecording(
1717
enableAudio: Boolean,
1818
options: RecordVideoOptions,
1919
callback: (video: Video) -> Unit,
20-
onError: (error: CameraError) -> Unit
20+
onError: (error: CameraError) -> Unit,
21+
onBytesWrittenCallback: (bytes: Long) -> Unit
2122
) {
2223
if (camera == null) throw CameraNotReadyError()
2324
if (recording != null) throw RecordingInProgressError()
@@ -49,7 +50,10 @@ fun CameraSession.startRecording(
4950

5051
is VideoRecordEvent.Pause -> Log.i(CameraSession.TAG, "Recording paused!")
5152

52-
is VideoRecordEvent.Status -> Log.i(CameraSession.TAG, "Status update! Recorded ${event.recordingStats.numBytesRecorded} bytes.")
53+
is VideoRecordEvent.Status -> {
54+
Log.i(CameraSession.TAG, "Status update! Recorded ${event.recordingStats.numBytesRecorded} bytes.")
55+
onBytesWrittenCallback(event.recordingStats.numBytesRecorded)
56+
}
5357

5458
is VideoRecordEvent.Finalize -> {
5559
if (isRecordingCanceled) {

package/android/src/main/java/com/mrousavy/camera/core/CameraSession.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,5 +221,6 @@ class CameraSession(internal val context: Context, internal val callback: Callba
221221
fun onOutputOrientationChanged(outputOrientation: Orientation)
222222
fun onPreviewOrientationChanged(previewOrientation: Orientation)
223223
fun onCodeScanned(codes: List<Barcode>, scannerFrame: CodeScannerFrame)
224+
fun onBytesWrittenVideo(bytesWritten: Double)
224225
}
225226
}

package/android/src/main/java/com/mrousavy/camera/react/CameraView+Events.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,17 @@ fun CameraView.invokeOnAverageFpsChanged(averageFps: Double) {
125125
this.sendEvent(event)
126126
}
127127

128+
fun CameraView.invokeOnBytesWrittenVideo(bytesWritten: Double) {
129+
Log.i(CameraView.TAG, "invokeOnBytesWrittenVideo($bytesWritten)")
130+
131+
val surfaceId = UIManagerHelper.getSurfaceId(this)
132+
val data = Arguments.createMap()
133+
data.putDouble("bytesWritten", bytesWritten)
134+
135+
val event = BytesWrittenVideoEvent(surfaceId, id, data)
136+
this.sendEvent(event)
137+
}
138+
128139
fun CameraView.invokeOnCodeScanned(barcodes: List<Barcode>, scannerFrame: CodeScannerFrame) {
129140
val codes = Arguments.createArray()
130141
barcodes.forEach { barcode ->

package/android/src/main/java/com/mrousavy/camera/react/CameraView+RecordVideo.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ import com.mrousavy.camera.core.types.Video
1717
import com.mrousavy.camera.react.utils.makeErrorMap
1818

1919
fun CameraView.startRecording(options: RecordVideoOptions, onRecordCallback: Callback) {
20-
// check audio permission
20+
val onBytesWrittenCallback = { bytes: Long ->
21+
this.onBytesWrittenVideo(bytes.toDouble())
22+
}
2123
if (audio) {
2224
if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
2325
throw MicrophonePermissionError()
@@ -36,7 +38,7 @@ fun CameraView.startRecording(options: RecordVideoOptions, onRecordCallback: Cal
3638
val errorMap = makeErrorMap(error.code, error.message)
3739
onRecordCallback(null, errorMap)
3840
}
39-
cameraSession.startRecording(audio, options, callback, onError)
41+
cameraSession.startRecording(audio, options, callback, onError, onBytesWrittenCallback)
4042
}
4143

4244
fun CameraView.pauseRecording() {

package/android/src/main/java/com/mrousavy/camera/react/CameraView.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,4 +350,8 @@ class CameraView(context: Context) :
350350
override fun onAverageFpsChanged(averageFps: Double) {
351351
invokeOnAverageFpsChanged(averageFps)
352352
}
353+
354+
override fun onBytesWrittenVideo(bytesWritten: Double) {
355+
invokeOnBytesWrittenVideo(bytesWritten)
356+
}
353357
}

package/android/src/main/java/com/mrousavy/camera/react/CameraViewManager.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class CameraViewManager : ViewGroupManager<CameraView>() {
4141
.put(CameraOutputOrientationChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onOutputOrientationChanged"))
4242
.put(CameraPreviewOrientationChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onPreviewOrientationChanged"))
4343
.put(AverageFpsChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAverageFpsChanged"))
44+
.put(BytesWrittenVideoEvent.EVENT_NAME, MapBuilder.of("registrationName", "onBytesWrittenVideo"))
4445
.build()
4546

4647
override fun getName(): String = TAG

package/android/src/main/java/com/mrousavy/camera/react/Events.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,11 @@ class CameraCodeScannedEvent(surfaceId: Int, viewId: Int, private val data: Writ
102102
const val EVENT_NAME = "topCameraCodeScanned"
103103
}
104104
}
105+
class BytesWrittenVideoEvent(surfaceId: Int, viewId: Int, private val data: WritableMap) :
106+
Event<BytesWrittenVideoEvent>(surfaceId, viewId) {
107+
override fun getEventName() = EVENT_NAME
108+
override fun getEventData() = data
109+
companion object {
110+
const val EVENT_NAME = "bytesWrittenVideoEvent"
111+
}
112+
}

0 commit comments

Comments
 (0)