react-native-photo-video-editor 0.3.0 → 0.3.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.3.1
6
+
7
+ - Reduce Android large-video memory pressure with a heap-aware preview sample-buffer target (up to 16 MiB), size-first buffering, and release of preview samples/decoders during export. Restore the paused preview after export cancellation or failure.
8
+
5
9
  ## 0.3.0
6
10
 
7
11
  - Breaking API change: migrate `initialStickerId: 'brand'` to `initialStickerIds: ['brand']`.
@@ -2290,7 +2290,7 @@ class PhotoVideoEditorActivity : Activity() {
2290
2290
  finishWithError("Nothing to export.", "E_INTERNAL")
2291
2291
  return
2292
2292
  }
2293
- session.player.pause()
2293
+ session.stopPreviewForExport()
2294
2294
  videoExportProgressView.visibility = View.VISIBLE
2295
2295
  val exporter = VideoExporter(applicationContext)
2296
2296
  videoExporter = exporter
@@ -2321,11 +2321,13 @@ class PhotoVideoEditorActivity : Activity() {
2321
2321
  runOnUiThread {
2322
2322
  videoExporter = null
2323
2323
  videoExportProgressView.visibility = View.GONE
2324
+ session.restorePreviewAfterExport()
2324
2325
  Toast.makeText(this, error.message ?: "Unable to export the video.", Toast.LENGTH_LONG).show()
2325
2326
  }
2326
2327
  }
2327
2328
  )
2328
2329
  } catch (error: Exception) {
2330
+ session.restorePreviewAfterExport()
2329
2331
  videoExporter = null
2330
2332
  videoExportProgressView.visibility = View.GONE
2331
2333
  Toast.makeText(this, error.message ?: "Unable to export the video.", Toast.LENGTH_LONG).show()
@@ -2334,6 +2336,7 @@ class PhotoVideoEditorActivity : Activity() {
2334
2336
 
2335
2337
  private fun cancelVideoExport() {
2336
2338
  videoExporter?.cancel()
2339
+ videoSession?.restorePreviewAfterExport()
2337
2340
  videoExporter = null
2338
2341
  videoExportProgressView.visibility = View.GONE
2339
2342
  }
@@ -0,0 +1,10 @@
1
+ package com.photovideoeditor.video.render
2
+
3
+ /** Leave heap space for the host React Native app, decoded frames, and editor bitmaps. */
4
+ internal object VideoBufferBudget {
5
+ private const val MIB = 1024L * 1024L
6
+
7
+ // A target rather than a hard heap cap: Media3 can finish a sample after reaching it.
8
+ fun targetBytes(maxHeapBytes: Long): Int =
9
+ (maxHeapBytes / 16).coerceIn(2 * MIB, 16 * MIB).toInt()
10
+ }
@@ -6,6 +6,7 @@ import androidx.media3.common.MediaItem
6
6
  import androidx.media3.common.PlaybackException
7
7
  import androidx.media3.common.Player
8
8
  import androidx.media3.exoplayer.ExoPlayer
9
+ import androidx.media3.exoplayer.DefaultLoadControl
9
10
  import com.photovideoeditor.photo.render.PhotoLayerStack
10
11
  import java.io.File
11
12
 
@@ -21,7 +22,17 @@ class VideoEditSession(context: Context, val sourceUri: String) {
21
22
  private set
22
23
  var sourceHeight = 0
23
24
  private set
24
- val player: ExoPlayer = ExoPlayer.Builder(context).build()
25
+ // Bound compressed samples independently of bitrate/duration. Time-first buffering
26
+ // can otherwise exhaust the host app's heap on high-bitrate camera footage.
27
+ val player: ExoPlayer = ExoPlayer.Builder(context)
28
+ .setLoadControl(DefaultLoadControl.Builder()
29
+ .setTargetBufferBytes(VideoBufferBudget.targetBytes(Runtime.getRuntime().maxMemory()))
30
+ .setBufferDurationsMs(2_000, 5_000, 500, 1_000)
31
+ .setPrioritizeTimeOverSizeThresholds(false)
32
+ .setBackBuffer(0, false)
33
+ .build())
34
+ .build()
35
+ private var previewStoppedForExport = false
25
36
 
26
37
  /** Text/sticker/shape overlays. Reuses the photo layer model/stack — see `PhotoLayer.startMs`/`endMs` for timing. */
27
38
  val layerStack = PhotoLayerStack()
@@ -133,6 +144,21 @@ class VideoEditSession(context: Context, val sourceUri: String) {
133
144
  }
134
145
  }
135
146
 
147
+ /** Pause alone retains samples and decoders; stop releases them while retaining the playlist/position. */
148
+ fun stopPreviewForExport() {
149
+ if (previewStoppedForExport) return
150
+ previewStoppedForExport = true
151
+ player.pause()
152
+ player.stop()
153
+ }
154
+
155
+ /** Export failure/cancellation returns to the same paused preview. */
156
+ fun restorePreviewAfterExport() {
157
+ if (!previewStoppedForExport) return
158
+ previewStoppedForExport = false
159
+ player.prepare()
160
+ }
161
+
136
162
  fun release() {
137
163
  onClipsReady = null
138
164
  onPlaybackError = null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-photo-video-editor",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Native photo and video editor for React Native, powered by Kotlin and Swift.",
5
5
  "main": "./lib/module/index.js",
6
6
  "module": "./lib/module/index.js",