@remotion/media 4.0.506 → 4.0.507

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.
@@ -2789,7 +2789,7 @@ import {
2789
2789
 
2790
2790
  // src/caches.ts
2791
2791
  import React2 from "react";
2792
- import { cancelRender, Internals as Internals12 } from "remotion";
2792
+ import { cancelRender, Internals as Internals14 } from "remotion";
2793
2793
 
2794
2794
  // src/audio-extraction/audio-manager.ts
2795
2795
  import { Internals as Internals9 } from "remotion";
@@ -2991,8 +2991,11 @@ var makeAudioIterator2 = ({
2991
2991
  };
2992
2992
 
2993
2993
  // src/audio-extraction/audio-manager.ts
2994
- var makeAudioManager = () => {
2994
+ var makeAudioManager = ({
2995
+ getTotalCacheStats
2996
+ }) => {
2995
2997
  const iterators = [];
2998
+ let disposed = false;
2996
2999
  const makeIterator = ({
2997
3000
  timeInSeconds,
2998
3001
  src,
@@ -3053,6 +3056,9 @@ var makeAudioManager = () => {
3053
3056
  logLevel,
3054
3057
  maxCacheSize
3055
3058
  }) => {
3059
+ if (disposed) {
3060
+ throw new Error("Media cache has already been disposed");
3061
+ }
3056
3062
  let attempts = 0;
3057
3063
  const maxAttempts = 3;
3058
3064
  while ((await getTotalCacheStats()).totalSize > maxCacheSize && attempts < maxAttempts) {
@@ -3075,6 +3081,9 @@ var makeAudioManager = () => {
3075
3081
  }
3076
3082
  }
3077
3083
  deleteDuplicateIterators(logLevel);
3084
+ if (disposed) {
3085
+ throw new Error("Media cache has already been disposed");
3086
+ }
3078
3087
  return makeIterator({
3079
3088
  src,
3080
3089
  timeInSeconds,
@@ -3099,6 +3108,19 @@ var makeAudioManager = () => {
3099
3108
  iterator.logOpenFrames();
3100
3109
  }
3101
3110
  };
3111
+ const clearAll = () => {
3112
+ for (const iterator of iterators) {
3113
+ iterator.prepareForDeletion();
3114
+ }
3115
+ iterators.length = 0;
3116
+ };
3117
+ const dispose = () => {
3118
+ if (disposed) {
3119
+ return;
3120
+ }
3121
+ disposed = true;
3122
+ clearAll();
3123
+ };
3102
3124
  let queue = Promise.resolve(undefined);
3103
3125
  return {
3104
3126
  getIterator: ({
@@ -3124,13 +3146,251 @@ var makeAudioManager = () => {
3124
3146
  getCacheStats,
3125
3147
  getIteratorMostInThePast,
3126
3148
  logOpenFrames,
3127
- deleteDuplicateIterators
3149
+ deleteDuplicateIterators,
3150
+ clearAll,
3151
+ dispose
3128
3152
  };
3129
3153
  };
3130
3154
 
3131
- // src/video-extraction/keyframe-manager.ts
3155
+ // src/get-sink.ts
3132
3156
  import { Internals as Internals11 } from "remotion";
3133
3157
 
3158
+ // src/video-extraction/get-frames-since-keyframe.ts
3159
+ import {
3160
+ ALL_FORMATS as ALL_FORMATS2,
3161
+ AudioSampleSink,
3162
+ EncodedPacketSink,
3163
+ Input as Input2,
3164
+ MATROSKA,
3165
+ UrlSource as UrlSource2,
3166
+ VideoSampleSink,
3167
+ WEBM
3168
+ } from "mediabunny";
3169
+ import { Internals as Internals10 } from "remotion";
3170
+
3171
+ // src/browser-can-use-webgl2.ts
3172
+ var browserCanUseWebGl2 = null;
3173
+ var browserCanUseWebGl2Uncached = () => {
3174
+ const canvas = new OffscreenCanvas(1, 1);
3175
+ const context = canvas.getContext("webgl2");
3176
+ return context !== null;
3177
+ };
3178
+ var canBrowserUseWebGl2 = () => {
3179
+ if (browserCanUseWebGl2 !== null) {
3180
+ return browserCanUseWebGl2;
3181
+ }
3182
+ browserCanUseWebGl2 = browserCanUseWebGl2Uncached();
3183
+ return browserCanUseWebGl2;
3184
+ };
3185
+
3186
+ // src/video-extraction/remember-actual-matroska-timestamps.ts
3187
+ var rememberActualMatroskaTimestamps = (isMatroska) => {
3188
+ const observations = [];
3189
+ const observeTimestamp = (startTime) => {
3190
+ if (!isMatroska) {
3191
+ return;
3192
+ }
3193
+ observations.push(startTime);
3194
+ };
3195
+ const getRealTimestamp = (observedTimestamp) => {
3196
+ if (!isMatroska) {
3197
+ return observedTimestamp;
3198
+ }
3199
+ return observations.find((observation) => Math.abs(observedTimestamp - observation) < 0.001) ?? null;
3200
+ };
3201
+ return {
3202
+ observeTimestamp,
3203
+ getRealTimestamp
3204
+ };
3205
+ };
3206
+
3207
+ // src/video-extraction/get-frames-since-keyframe.ts
3208
+ var getRetryDelay = () => {
3209
+ return null;
3210
+ };
3211
+ var getFormatOrNullOrNetworkError = async (input) => {
3212
+ try {
3213
+ return await input.getFormat();
3214
+ } catch (err) {
3215
+ if (isNetworkError(err)) {
3216
+ return "network-error";
3217
+ }
3218
+ return null;
3219
+ }
3220
+ };
3221
+ var makeSinks = (src, logLevel, credentials, requestInit) => {
3222
+ const resolvedRequestInit = resolveRequestInit({ credentials, requestInit });
3223
+ const input = new Input2({
3224
+ formats: ALL_FORMATS2,
3225
+ source: new UrlSource2(src, {
3226
+ getRetryDelay,
3227
+ ...resolvedRequestInit ? { requestInit: resolvedRequestInit } : undefined
3228
+ })
3229
+ });
3230
+ const getSinks = async () => {
3231
+ const format = await getFormatOrNullOrNetworkError(input);
3232
+ const isMatroska = format === MATROSKA || format === WEBM;
3233
+ const getVideoSinks = async () => {
3234
+ if (format === "network-error") {
3235
+ return "network-error";
3236
+ }
3237
+ if (format === null) {
3238
+ return "unknown-container-format";
3239
+ }
3240
+ const videoTrack = await input.getPrimaryVideoTrack();
3241
+ if (!videoTrack) {
3242
+ return "no-video-track";
3243
+ }
3244
+ if (await videoTrack.isLive()) {
3245
+ throw new Error("Live streams are not currently supported by Remotion. Sorry! Source: " + src);
3246
+ }
3247
+ if (await videoTrack.isRelativeToUnixEpoch()) {
3248
+ throw new Error("Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: " + src);
3249
+ }
3250
+ const canDecode = await videoTrack.canDecode();
3251
+ if (!canDecode) {
3252
+ if (videoTrack.codec === "prores") {
3253
+ return "cannot-decode-prores";
3254
+ }
3255
+ return "cannot-decode";
3256
+ }
3257
+ const sampleSink = new VideoSampleSink(videoTrack);
3258
+ const packetSink = new EncodedPacketSink(videoTrack);
3259
+ const startPacket = await packetSink.getFirstPacket({
3260
+ verifyKeyPackets: true
3261
+ });
3262
+ const hasAlpha = startPacket?.sideData.alpha;
3263
+ if (hasAlpha && !canBrowserUseWebGl2()) {
3264
+ Internals10.Log.warn({ logLevel, tag: "@remotion/media" }, `WebGL2 is not available, using the non-fast CPU path to decode alpha for ${src}.`);
3265
+ }
3266
+ return {
3267
+ sampleSink
3268
+ };
3269
+ };
3270
+ let videoSinksPromise = null;
3271
+ const getVideoSinksPromise = () => {
3272
+ if (videoSinksPromise) {
3273
+ return videoSinksPromise;
3274
+ }
3275
+ videoSinksPromise = getVideoSinks();
3276
+ return videoSinksPromise;
3277
+ };
3278
+ const audioSinksPromise = {};
3279
+ const getAudioSinks = async (index) => {
3280
+ if (format === null) {
3281
+ return "unknown-container-format";
3282
+ }
3283
+ if (format === "network-error") {
3284
+ return "network-error";
3285
+ }
3286
+ const [videoTrack, audioTracks] = await Promise.all([
3287
+ input.getPrimaryVideoTrack(),
3288
+ input.getAudioTracks()
3289
+ ]);
3290
+ const audioTrack = await resolveAudioTrack({
3291
+ videoTrack,
3292
+ audioTracks,
3293
+ audioStreamIndex: index
3294
+ });
3295
+ if (!audioTrack) {
3296
+ return "no-audio-track";
3297
+ }
3298
+ const canDecode = await audioTrack.canDecode();
3299
+ if (!canDecode) {
3300
+ return "cannot-decode-audio";
3301
+ }
3302
+ return {
3303
+ sampleSink: new AudioSampleSink(audioTrack)
3304
+ };
3305
+ };
3306
+ const getAudioSinksPromise = (index) => {
3307
+ const keyIndex = index === null ? -1 : index;
3308
+ if (audioSinksPromise[keyIndex]) {
3309
+ return audioSinksPromise[keyIndex];
3310
+ }
3311
+ audioSinksPromise[keyIndex] = getAudioSinks(index);
3312
+ return audioSinksPromise[keyIndex];
3313
+ };
3314
+ return {
3315
+ getVideo: () => getVideoSinksPromise(),
3316
+ getAudio: (index) => getAudioSinksPromise(index),
3317
+ actualMatroskaTimestamps: rememberActualMatroskaTimestamps(isMatroska),
3318
+ isMatroska,
3319
+ getDuration: () => {
3320
+ return getDurationOrCompute(input);
3321
+ }
3322
+ };
3323
+ };
3324
+ return {
3325
+ promise: getSinks(),
3326
+ dispose: () => input.dispose()
3327
+ };
3328
+ };
3329
+
3330
+ // src/get-sink.ts
3331
+ var getSinkCacheKey = ({
3332
+ src,
3333
+ credentials,
3334
+ requestInit
3335
+ }) => JSON.stringify([
3336
+ src,
3337
+ credentials,
3338
+ getMediaRequestInitFingerprint(requestInit)
3339
+ ]);
3340
+ var makeSinkManager = () => {
3341
+ const sinkPromises = {};
3342
+ const inputDisposers = {};
3343
+ let disposed = false;
3344
+ return {
3345
+ getSink: (src, logLevel, credentials, requestInit) => {
3346
+ if (disposed) {
3347
+ return Promise.reject(new Error("Media cache has already been disposed"));
3348
+ }
3349
+ const normalizedRequestInit = normalizeMediaRequestInit(requestInit);
3350
+ const cacheKey = getSinkCacheKey({
3351
+ src,
3352
+ credentials,
3353
+ requestInit: normalizedRequestInit
3354
+ });
3355
+ let promise = sinkPromises[cacheKey];
3356
+ if (!promise) {
3357
+ Internals11.Log.verbose({
3358
+ logLevel,
3359
+ tag: "@remotion/media"
3360
+ }, `Sink for ${src} was not found, creating new sink`);
3361
+ const sinks = makeSinks(src, logLevel, credentials, normalizedRequestInit);
3362
+ promise = sinks.promise;
3363
+ sinkPromises[cacheKey] = promise;
3364
+ inputDisposers[cacheKey] = sinks.dispose;
3365
+ }
3366
+ return promise;
3367
+ },
3368
+ dispose: () => {
3369
+ if (disposed) {
3370
+ return;
3371
+ }
3372
+ disposed = true;
3373
+ let firstError = null;
3374
+ for (const cacheKey of Object.keys(inputDisposers)) {
3375
+ try {
3376
+ inputDisposers[cacheKey]();
3377
+ } catch (error) {
3378
+ firstError ??= error;
3379
+ } finally {
3380
+ delete inputDisposers[cacheKey];
3381
+ delete sinkPromises[cacheKey];
3382
+ }
3383
+ }
3384
+ if (firstError !== null) {
3385
+ throw firstError;
3386
+ }
3387
+ }
3388
+ };
3389
+ };
3390
+
3391
+ // src/video-extraction/keyframe-manager.ts
3392
+ import { Internals as Internals13 } from "remotion";
3393
+
3134
3394
  // src/render-timestamp-range.ts
3135
3395
  var renderTimestampRange = (timestamps) => {
3136
3396
  if (timestamps.length === 0) {
@@ -3143,12 +3403,13 @@ var renderTimestampRange = (timestamps) => {
3143
3403
  };
3144
3404
 
3145
3405
  // src/video-extraction/keyframe-bank.ts
3146
- import { Internals as Internals10 } from "remotion";
3406
+ import { Internals as Internals12 } from "remotion";
3147
3407
 
3148
3408
  // src/video-extraction/get-allocation-size.ts
3409
+ var BYTES_PER_PIXEL_FOR_OPAQUE_FRAME = 3;
3149
3410
  var getAllocationSize = (sample) => {
3150
3411
  if (sample.format === null) {
3151
- return sample.codedHeight * sample.codedWidth * 4;
3412
+ return sample.codedHeight * sample.codedWidth * BYTES_PER_PIXEL_FOR_OPAQUE_FRAME;
3152
3413
  }
3153
3414
  return sample.allocationSize();
3154
3415
  };
@@ -3222,7 +3483,7 @@ var makeKeyframeBank = async ({
3222
3483
  }
3223
3484
  }
3224
3485
  if (deletedTimestamps.length > 0) {
3225
- Internals10.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted ${deletedTimestamps.length} frame${deletedTimestamps.length === 1 ? "" : "s"} ${renderTimestampRange(deletedTimestamps)} for src ${src} because it is lower than ${timestampInSeconds}. Remaining: ${renderTimestampRange(frameTimestamps)}`);
3486
+ Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted ${deletedTimestamps.length} frame${deletedTimestamps.length === 1 ? "" : "s"} ${renderTimestampRange(deletedTimestamps)} for src ${src} because it is lower than ${timestampInSeconds}. Remaining: ${renderTimestampRange(frameTimestamps)}`);
3226
3487
  }
3227
3488
  };
3228
3489
  const hasDecodedEnoughForTimestamp = (timestamp) => {
@@ -3251,7 +3512,7 @@ var makeKeyframeBank = async ({
3251
3512
  frameTimestamps.push(frame.timestamp);
3252
3513
  allocationSize += getAllocationSize(frame);
3253
3514
  lastUsed = Date.now();
3254
- Internals10.Log.trace({ logLevel, tag: "@remotion/media" }, `Added frame at ${frame.timestamp}sec to bank`);
3515
+ Internals12.Log.trace({ logLevel, tag: "@remotion/media" }, `Added frame at ${frame.timestamp}sec to bank`);
3255
3516
  };
3256
3517
  const ensureEnoughFramesForTimestamp = async (timestampInSeconds, logLevel, fps) => {
3257
3518
  while (!hasDecodedEnoughForTimestamp(timestampInSeconds)) {
@@ -3306,7 +3567,7 @@ var makeKeyframeBank = async ({
3306
3567
  throw new Error("No first frame found");
3307
3568
  }
3308
3569
  const startTimestampInSeconds = firstFrame.value.timestamp;
3309
- Internals10.Log.verbose({ logLevel: parentLogLevel, tag: "@remotion/media" }, `Creating keyframe bank from ${startTimestampInSeconds}sec`);
3570
+ Internals12.Log.verbose({ logLevel: parentLogLevel, tag: "@remotion/media" }, `Creating keyframe bank from ${startTimestampInSeconds}sec`);
3310
3571
  addFrame(firstFrame.value, parentLogLevel);
3311
3572
  const getRangeOfTimestamps = () => {
3312
3573
  if (frameTimestamps.length === 0) {
@@ -3323,7 +3584,7 @@ var makeKeyframeBank = async ({
3323
3584
  const prepareForDeletion = (logLevel, reason) => {
3324
3585
  const range = getRangeOfTimestamps();
3325
3586
  if (range) {
3326
- Internals10.Log.verbose({ logLevel, tag: "@remotion/media" }, `Preparing for deletion (${reason}) of keyframe bank from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec`);
3587
+ Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Preparing for deletion (${reason}) of keyframe bank from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec`);
3327
3588
  }
3328
3589
  let framesDeleted = 0;
3329
3590
  for (const frameTimestamp of frameTimestamps.slice()) {
@@ -3384,11 +3645,23 @@ var makeKeyframeBank = async ({
3384
3645
  };
3385
3646
 
3386
3647
  // src/video-extraction/keyframe-manager.ts
3387
- var makeKeyframeManager = () => {
3648
+ var makeKeyframeManager = ({
3649
+ getTotalCacheStats
3650
+ }) => {
3388
3651
  let sources = {};
3389
- const addKeyframeBank = ({ src, bank }) => {
3652
+ let disposed = false;
3653
+ const addKeyframeBank = ({
3654
+ src,
3655
+ bank,
3656
+ logLevel
3657
+ }) => {
3658
+ if (disposed) {
3659
+ bank.prepareForDeletion(logLevel, "media cache was disposed");
3660
+ return false;
3661
+ }
3390
3662
  sources[src] = sources[src] ?? [];
3391
3663
  sources[src].push(bank);
3664
+ return true;
3392
3665
  };
3393
3666
  const logCacheStats = (logLevel) => {
3394
3667
  let count = 0;
@@ -3401,10 +3674,10 @@ var makeKeyframeManager = () => {
3401
3674
  if (size === 0) {
3402
3675
  continue;
3403
3676
  }
3404
- Internals11.Log.verbose({ logLevel, tag: "@remotion/media" }, `Open frames for src ${src}: ${renderTimestampRange(timestamps)}`);
3677
+ Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `Open frames for src ${src}: ${renderTimestampRange(timestamps)}`);
3405
3678
  }
3406
3679
  }
3407
- Internals11.Log.verbose({ logLevel, tag: "@remotion/media" }, `Video cache stats: ${count} open frames, ${totalSize} bytes`);
3680
+ Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `Video cache stats: ${count} open frames, ${totalSize} bytes`);
3408
3681
  };
3409
3682
  const getCacheStats = () => {
3410
3683
  let count = 0;
@@ -3458,7 +3731,7 @@ var makeKeyframeManager = () => {
3458
3731
  const { framesDeleted } = mostInThePastBank.prepareForDeletion(logLevel, "deleted oldest keyframe bank to stay under max cache size");
3459
3732
  sources[mostInThePastSrc].splice(mostInThePastIndex, 1);
3460
3733
  if (range) {
3461
- Internals11.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted ${framesDeleted} frames for src ${mostInThePastSrc} from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec to free up memory.`);
3734
+ Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted ${framesDeleted} frames for src ${mostInThePastSrc} from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec to free up memory.`);
3462
3735
  }
3463
3736
  }
3464
3737
  return { finish: false };
@@ -3472,12 +3745,12 @@ var makeKeyframeManager = () => {
3472
3745
  if (finish) {
3473
3746
  break;
3474
3747
  }
3475
- Internals11.Log.verbose({ logLevel, tag: "@remotion/media" }, "Deleted oldest keyframe bank to stay under max cache size", (cacheStats.totalSize / 1024 / 1024).toFixed(1), "out of", (maxCacheSize / 1024 / 1024).toFixed(1));
3748
+ Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, "Deleted oldest keyframe bank to stay under max cache size", (cacheStats.totalSize / 1024 / 1024).toFixed(1), "out of", (maxCacheSize / 1024 / 1024).toFixed(1));
3476
3749
  cacheStats = getTotalCacheStats();
3477
3750
  attempts++;
3478
3751
  }
3479
3752
  if (cacheStats.totalSize > maxCacheSize && attempts >= maxAttempts) {
3480
- Internals11.Log.warn({ logLevel, tag: "@remotion/media" }, `Exceeded max cache size after ${maxAttempts} attempts. Remaining cache size: ${(cacheStats.totalSize / 1024 / 1024).toFixed(1)} MB, target was ${(maxCacheSize / 1024 / 1024).toFixed(1)} MB.`);
3753
+ Internals13.Log.warn({ logLevel, tag: "@remotion/media" }, `Exceeded max cache size after ${maxAttempts} attempts. Remaining cache size: ${(cacheStats.totalSize / 1024 / 1024).toFixed(1)} MB, target was ${(maxCacheSize / 1024 / 1024).toFixed(1)} MB.`);
3481
3754
  }
3482
3755
  };
3483
3756
  const clearKeyframeBanksBeforeTime = ({
@@ -3498,7 +3771,7 @@ var makeKeyframeManager = () => {
3498
3771
  }
3499
3772
  if (range.lastTimestamp < threshold) {
3500
3773
  bank.prepareForDeletion(logLevel, "cleared before threshold " + threshold);
3501
- Internals11.Log.verbose({ logLevel, tag: "@remotion/media" }, `[Video] Cleared frames for src ${src} from ${range.firstTimestamp}sec to ${range.lastTimestamp}sec`);
3774
+ Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `[Video] Cleared frames for src ${src} from ${range.firstTimestamp}sec to ${range.lastTimestamp}sec`);
3502
3775
  const bankIndex = banks.indexOf(bank);
3503
3776
  delete sources[src][bankIndex];
3504
3777
  } else {
@@ -3520,21 +3793,23 @@ var makeKeyframeManager = () => {
3520
3793
  const existingBanks = sources[src] ?? [];
3521
3794
  const existingBank = existingBanks?.find((bank) => bank.canSatisfyTimestamp(timestamp));
3522
3795
  if (!existingBank) {
3523
- Internals11.Log.trace({ logLevel, tag: "@remotion/media" }, `Creating new keyframe bank for src ${src} at timestamp ${timestamp}`);
3796
+ Internals13.Log.trace({ logLevel, tag: "@remotion/media" }, `Creating new keyframe bank for src ${src} at timestamp ${timestamp}`);
3524
3797
  const newKeyframeBank = await makeKeyframeBank({
3525
3798
  videoSampleSink,
3526
3799
  logLevel,
3527
3800
  src,
3528
3801
  initialTimestampRequest: timestamp
3529
3802
  });
3530
- addKeyframeBank({ src, bank: newKeyframeBank });
3803
+ if (!addKeyframeBank({ src, bank: newKeyframeBank, logLevel })) {
3804
+ return null;
3805
+ }
3531
3806
  return newKeyframeBank;
3532
3807
  }
3533
3808
  if (existingBank.canSatisfyTimestamp(timestamp)) {
3534
- Internals11.Log.trace({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists and satisfies timestamp ${timestamp}`);
3809
+ Internals13.Log.trace({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists and satisfies timestamp ${timestamp}`);
3535
3810
  return existingBank;
3536
3811
  }
3537
- Internals11.Log.verbose({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists but frame at time ${timestamp} does not exist anymore.`);
3812
+ Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists but frame at time ${timestamp} does not exist anymore.`);
3538
3813
  existingBank.prepareForDeletion(logLevel, "already existed but evicted");
3539
3814
  sources[src] = sources[src].filter((bank) => bank !== existingBank);
3540
3815
  const replacementKeybank = await makeKeyframeBank({
@@ -3543,7 +3818,9 @@ var makeKeyframeManager = () => {
3543
3818
  logLevel,
3544
3819
  src
3545
3820
  });
3546
- addKeyframeBank({ src, bank: replacementKeybank });
3821
+ if (!addKeyframeBank({ src, bank: replacementKeybank, logLevel })) {
3822
+ return null;
3823
+ }
3547
3824
  return replacementKeybank;
3548
3825
  };
3549
3826
  const requestKeyframeBank = async ({
@@ -3554,6 +3831,9 @@ var makeKeyframeManager = () => {
3554
3831
  maxCacheSize,
3555
3832
  fps
3556
3833
  }) => {
3834
+ if (disposed) {
3835
+ return null;
3836
+ }
3557
3837
  ensureToStayUnderMaxCacheSize(logLevel, maxCacheSize);
3558
3838
  clearKeyframeBanksBeforeTime({
3559
3839
  timestampInSeconds: timestamp,
@@ -3580,6 +3860,13 @@ var makeKeyframeManager = () => {
3580
3860
  }
3581
3861
  sources = {};
3582
3862
  };
3863
+ const dispose = (logLevel) => {
3864
+ if (disposed) {
3865
+ return;
3866
+ }
3867
+ disposed = true;
3868
+ clearAll(logLevel);
3869
+ };
3583
3870
  let queue = Promise.resolve(undefined);
3584
3871
  return {
3585
3872
  requestKeyframeBank: ({
@@ -3601,22 +3888,96 @@ var makeKeyframeManager = () => {
3601
3888
  return queue;
3602
3889
  },
3603
3890
  getCacheStats,
3604
- clearAll
3891
+ clearAll,
3892
+ dispose
3605
3893
  };
3606
3894
  };
3607
3895
 
3608
3896
  // src/caches.ts
3609
3897
  var getSafeWindowOfMonotonicity = (fps) => 0.2 * 30 / fps;
3610
- var keyframeManager = makeKeyframeManager();
3611
- var audioManager = makeAudioManager();
3612
- var getTotalCacheStats = () => {
3613
- const keyframeManagerCacheStats = keyframeManager.getCacheStats();
3614
- const audioManagerCacheStats = audioManager.getCacheStats();
3898
+ var makeMediaCache = () => {
3899
+ const sinkManager = makeSinkManager();
3900
+ const managerInstances = {
3901
+ keyframe: null,
3902
+ audio: null
3903
+ };
3904
+ const getCacheStats = () => {
3905
+ const { keyframe: currentKeyframeManager, audio: currentAudioManager } = managerInstances;
3906
+ if (currentKeyframeManager === null || currentAudioManager === null) {
3907
+ throw new Error("Media cache managers have not been initialized");
3908
+ }
3909
+ const keyframeManagerCacheStats = currentKeyframeManager.getCacheStats();
3910
+ const audioManagerCacheStats = currentAudioManager.getCacheStats();
3911
+ return {
3912
+ count: keyframeManagerCacheStats.count + audioManagerCacheStats.count,
3913
+ totalSize: keyframeManagerCacheStats.totalSize + audioManagerCacheStats.totalSize
3914
+ };
3915
+ };
3916
+ const keyframeManagerInstance = makeKeyframeManager({
3917
+ getTotalCacheStats: getCacheStats
3918
+ });
3919
+ const audioManagerInstance = makeAudioManager({
3920
+ getTotalCacheStats: getCacheStats
3921
+ });
3922
+ managerInstances.keyframe = keyframeManagerInstance;
3923
+ managerInstances.audio = audioManagerInstance;
3924
+ let frameExtractionQueue = Promise.resolve(undefined);
3925
+ let audioExtractionQueue = Promise.resolve(undefined);
3926
+ let disposed = false;
3615
3927
  return {
3616
- count: keyframeManagerCacheStats.count + audioManagerCacheStats.count,
3617
- totalSize: keyframeManagerCacheStats.totalSize + audioManagerCacheStats.totalSize
3928
+ sinkManager,
3929
+ keyframeManager: keyframeManagerInstance,
3930
+ audioManager: audioManagerInstance,
3931
+ getTotalCacheStats: getCacheStats,
3932
+ isDisposed: () => disposed,
3933
+ queueFrameExtraction: (extract) => {
3934
+ const extraction = frameExtractionQueue.then(extract);
3935
+ frameExtractionQueue = extraction.catch(() => {
3936
+ return;
3937
+ });
3938
+ return extraction;
3939
+ },
3940
+ queueAudioExtraction: (extract) => {
3941
+ const extraction = audioExtractionQueue.then(extract);
3942
+ audioExtractionQueue = extraction.catch(() => {
3943
+ return;
3944
+ });
3945
+ return extraction;
3946
+ },
3947
+ dispose: (logLevel) => {
3948
+ if (disposed) {
3949
+ return;
3950
+ }
3951
+ disposed = true;
3952
+ try {
3953
+ keyframeManagerInstance.dispose(logLevel);
3954
+ } finally {
3955
+ try {
3956
+ audioManagerInstance.dispose();
3957
+ } finally {
3958
+ sinkManager.dispose();
3959
+ }
3960
+ }
3961
+ }
3618
3962
  };
3619
3963
  };
3964
+ var globalMediaCache = makeMediaCache();
3965
+ var useRenderMediaCache = (logLevel) => {
3966
+ const renderResourceManager = React2.useContext(Internals14.RenderResourceManagerContext);
3967
+ if (renderResourceManager === null) {
3968
+ return globalMediaCache;
3969
+ }
3970
+ return renderResourceManager.getOrCreateResource({
3971
+ key: "@remotion/media/cache",
3972
+ create: () => {
3973
+ const resource = makeMediaCache();
3974
+ return {
3975
+ resource,
3976
+ dispose: () => resource.dispose(logLevel)
3977
+ };
3978
+ }
3979
+ });
3980
+ };
3620
3981
  var getUncachedMaxCacheSize = (logLevel) => {
3621
3982
  if (typeof window !== "undefined" && window.remotion_mediaCacheSizeInBytes !== undefined && window.remotion_mediaCacheSizeInBytes !== null) {
3622
3983
  if (window.remotion_mediaCacheSizeInBytes < 240 * 1024 * 1024) {
@@ -3625,20 +3986,20 @@ var getUncachedMaxCacheSize = (logLevel) => {
3625
3986
  if (window.remotion_mediaCacheSizeInBytes > 20000 * 1024 * 1024) {
3626
3987
  cancelRender(new Error(`The maximum value for the "mediaCacheSizeInBytes" prop is 20GB (${20000 * 1024 * 1024}), got: ${window.remotion_mediaCacheSizeInBytes}`));
3627
3988
  }
3628
- Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set using "mediaCacheSizeInBytes": ${(window.remotion_mediaCacheSizeInBytes / 1024 / 1024).toFixed(1)} MB`);
3989
+ Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set using "mediaCacheSizeInBytes": ${(window.remotion_mediaCacheSizeInBytes / 1024 / 1024).toFixed(1)} MB`);
3629
3990
  return window.remotion_mediaCacheSizeInBytes;
3630
3991
  }
3631
3992
  if (typeof window !== "undefined" && window.remotion_initialMemoryAvailable !== undefined && window.remotion_initialMemoryAvailable !== null) {
3632
3993
  const value = window.remotion_initialMemoryAvailable / 2;
3633
3994
  if (value < 500 * 1024 * 1024) {
3634
- Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on minimum value of 500MB (which is more than half of the available system memory!)`);
3995
+ Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on minimum value of 500MB (which is more than half of the available system memory!)`);
3635
3996
  return 500 * 1024 * 1024;
3636
3997
  }
3637
3998
  if (value > 20000 * 1024 * 1024) {
3638
- Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on maximum value of 20GB (which is less than half of the available system memory)`);
3999
+ Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on maximum value of 20GB (which is less than half of the available system memory)`);
3639
4000
  return 20000 * 1024 * 1024;
3640
4001
  }
3641
- Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on available memory (50% of available memory): ${(value / 1024 / 1024).toFixed(1)} MB`);
4002
+ Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on available memory (50% of available memory): ${(value / 1024 / 1024).toFixed(1)} MB`);
3642
4003
  return value;
3643
4004
  }
3644
4005
  return 1000 * 1000 * 1000;
@@ -3652,7 +4013,7 @@ var getMaxVideoCacheSize = (logLevel) => {
3652
4013
  return cachedMaxCacheSize;
3653
4014
  };
3654
4015
  var useMaxMediaCacheSize = (logLevel) => {
3655
- const context = React2.useContext(Internals12.MaxMediaCacheSizeContext);
4016
+ const context = React2.useContext(Internals14.MaxMediaCacheSizeContext);
3656
4017
  if (context === null) {
3657
4018
  return getMaxVideoCacheSize(logLevel);
3658
4019
  }
@@ -3905,205 +4266,6 @@ var combineAudioDataAndClosePrevious = (audioDataArray) => {
3905
4266
  };
3906
4267
  };
3907
4268
 
3908
- // src/get-sink.ts
3909
- import { Internals as Internals14 } from "remotion";
3910
-
3911
- // src/video-extraction/get-frames-since-keyframe.ts
3912
- import {
3913
- ALL_FORMATS as ALL_FORMATS2,
3914
- AudioSampleSink,
3915
- EncodedPacketSink,
3916
- Input as Input2,
3917
- MATROSKA,
3918
- UrlSource as UrlSource2,
3919
- VideoSampleSink,
3920
- WEBM
3921
- } from "mediabunny";
3922
- import { Internals as Internals13 } from "remotion";
3923
-
3924
- // src/browser-can-use-webgl2.ts
3925
- var browserCanUseWebGl2 = null;
3926
- var browserCanUseWebGl2Uncached = () => {
3927
- const canvas = new OffscreenCanvas(1, 1);
3928
- const context = canvas.getContext("webgl2");
3929
- return context !== null;
3930
- };
3931
- var canBrowserUseWebGl2 = () => {
3932
- if (browserCanUseWebGl2 !== null) {
3933
- return browserCanUseWebGl2;
3934
- }
3935
- browserCanUseWebGl2 = browserCanUseWebGl2Uncached();
3936
- return browserCanUseWebGl2;
3937
- };
3938
-
3939
- // src/video-extraction/remember-actual-matroska-timestamps.ts
3940
- var rememberActualMatroskaTimestamps = (isMatroska) => {
3941
- const observations = [];
3942
- const observeTimestamp = (startTime) => {
3943
- if (!isMatroska) {
3944
- return;
3945
- }
3946
- observations.push(startTime);
3947
- };
3948
- const getRealTimestamp = (observedTimestamp) => {
3949
- if (!isMatroska) {
3950
- return observedTimestamp;
3951
- }
3952
- return observations.find((observation) => Math.abs(observedTimestamp - observation) < 0.001) ?? null;
3953
- };
3954
- return {
3955
- observeTimestamp,
3956
- getRealTimestamp
3957
- };
3958
- };
3959
-
3960
- // src/video-extraction/get-frames-since-keyframe.ts
3961
- var getRetryDelay = () => {
3962
- return null;
3963
- };
3964
- var getFormatOrNullOrNetworkError = async (input) => {
3965
- try {
3966
- return await input.getFormat();
3967
- } catch (err) {
3968
- if (isNetworkError(err)) {
3969
- return "network-error";
3970
- }
3971
- return null;
3972
- }
3973
- };
3974
- var getSinks = async (src, logLevel, credentials, requestInit) => {
3975
- const resolvedRequestInit = resolveRequestInit({ credentials, requestInit });
3976
- const input = new Input2({
3977
- formats: ALL_FORMATS2,
3978
- source: new UrlSource2(src, {
3979
- getRetryDelay,
3980
- ...resolvedRequestInit ? { requestInit: resolvedRequestInit } : undefined
3981
- })
3982
- });
3983
- const format = await getFormatOrNullOrNetworkError(input);
3984
- const isMatroska = format === MATROSKA || format === WEBM;
3985
- const getVideoSinks = async () => {
3986
- if (format === "network-error") {
3987
- return "network-error";
3988
- }
3989
- if (format === null) {
3990
- return "unknown-container-format";
3991
- }
3992
- const videoTrack = await input.getPrimaryVideoTrack();
3993
- if (!videoTrack) {
3994
- return "no-video-track";
3995
- }
3996
- if (await videoTrack.isLive()) {
3997
- throw new Error("Live streams are not currently supported by Remotion. Sorry! Source: " + src);
3998
- }
3999
- if (await videoTrack.isRelativeToUnixEpoch()) {
4000
- throw new Error("Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: " + src);
4001
- }
4002
- const canDecode = await videoTrack.canDecode();
4003
- if (!canDecode) {
4004
- if (videoTrack.codec === "prores") {
4005
- return "cannot-decode-prores";
4006
- }
4007
- return "cannot-decode";
4008
- }
4009
- const sampleSink = new VideoSampleSink(videoTrack);
4010
- const packetSink = new EncodedPacketSink(videoTrack);
4011
- const startPacket = await packetSink.getFirstPacket({
4012
- verifyKeyPackets: true
4013
- });
4014
- const hasAlpha = startPacket?.sideData.alpha;
4015
- if (hasAlpha && !canBrowserUseWebGl2()) {
4016
- Internals13.Log.warn({ logLevel, tag: "@remotion/media" }, `WebGL2 is not available, using the non-fast CPU path to decode alpha for ${src}.`);
4017
- }
4018
- return {
4019
- sampleSink
4020
- };
4021
- };
4022
- let videoSinksPromise = null;
4023
- const getVideoSinksPromise = () => {
4024
- if (videoSinksPromise) {
4025
- return videoSinksPromise;
4026
- }
4027
- videoSinksPromise = getVideoSinks();
4028
- return videoSinksPromise;
4029
- };
4030
- const audioSinksPromise = {};
4031
- const getAudioSinks = async (index) => {
4032
- if (format === null) {
4033
- return "unknown-container-format";
4034
- }
4035
- if (format === "network-error") {
4036
- return "network-error";
4037
- }
4038
- const [videoTrack, audioTracks] = await Promise.all([
4039
- input.getPrimaryVideoTrack(),
4040
- input.getAudioTracks()
4041
- ]);
4042
- const audioTrack = await resolveAudioTrack({
4043
- videoTrack,
4044
- audioTracks,
4045
- audioStreamIndex: index
4046
- });
4047
- if (!audioTrack) {
4048
- return "no-audio-track";
4049
- }
4050
- const canDecode = await audioTrack.canDecode();
4051
- if (!canDecode) {
4052
- return "cannot-decode-audio";
4053
- }
4054
- return {
4055
- sampleSink: new AudioSampleSink(audioTrack)
4056
- };
4057
- };
4058
- const getAudioSinksPromise = (index) => {
4059
- const keyIndex = index === null ? -1 : index;
4060
- if (audioSinksPromise[keyIndex]) {
4061
- return audioSinksPromise[keyIndex];
4062
- }
4063
- audioSinksPromise[keyIndex] = getAudioSinks(index);
4064
- return audioSinksPromise[keyIndex];
4065
- };
4066
- return {
4067
- getVideo: () => getVideoSinksPromise(),
4068
- getAudio: (index) => getAudioSinksPromise(index),
4069
- actualMatroskaTimestamps: rememberActualMatroskaTimestamps(isMatroska),
4070
- isMatroska,
4071
- getDuration: () => {
4072
- return getDurationOrCompute(input);
4073
- }
4074
- };
4075
- };
4076
-
4077
- // src/get-sink.ts
4078
- var sinkPromises = {};
4079
- var getSinkCacheKey = ({
4080
- src,
4081
- credentials,
4082
- requestInit
4083
- }) => JSON.stringify([
4084
- src,
4085
- credentials,
4086
- getMediaRequestInitFingerprint(requestInit)
4087
- ]);
4088
- var getSink = (src, logLevel, credentials, requestInit) => {
4089
- const normalizedRequestInit = normalizeMediaRequestInit(requestInit);
4090
- const cacheKey = getSinkCacheKey({
4091
- src,
4092
- credentials,
4093
- requestInit: normalizedRequestInit
4094
- });
4095
- let promise = sinkPromises[cacheKey];
4096
- if (!promise) {
4097
- Internals14.Log.verbose({
4098
- logLevel,
4099
- tag: "@remotion/media"
4100
- }, `Sink for ${src} was not found, creating new sink`);
4101
- promise = getSinks(src, logLevel, credentials, normalizedRequestInit);
4102
- sinkPromises[cacheKey] = promise;
4103
- }
4104
- return promise;
4105
- };
4106
-
4107
4269
  // src/audio-extraction/extract-audio.ts
4108
4270
  var extractAudioInternal = async ({
4109
4271
  src,
@@ -4118,9 +4280,10 @@ var extractAudioInternal = async ({
4118
4280
  fps,
4119
4281
  maxCacheSize,
4120
4282
  credentials,
4121
- requestInit
4283
+ requestInit,
4284
+ mediaCache
4122
4285
  }) => {
4123
- const { getAudio, actualMatroskaTimestamps, isMatroska, getDuration } = await getSink(src, logLevel, credentials, requestInit);
4286
+ const { getAudio, actualMatroskaTimestamps, isMatroska, getDuration } = await mediaCache.sinkManager.getSink(src, logLevel, credentials, requestInit);
4124
4287
  let mediaDurationInSeconds = null;
4125
4288
  if (loop) {
4126
4289
  mediaDurationInSeconds = await getDuration();
@@ -4153,7 +4316,7 @@ var extractAudioInternal = async ({
4153
4316
  return { data: null, durationInSeconds: mediaDurationInSeconds };
4154
4317
  }
4155
4318
  try {
4156
- const sampleIterator = await audioManager.getIterator({
4319
+ const sampleIterator = await mediaCache.audioManager.getIterator({
4157
4320
  src,
4158
4321
  timeInSeconds,
4159
4322
  audioSampleSink: audio.sampleSink,
@@ -4164,7 +4327,7 @@ var extractAudioInternal = async ({
4164
4327
  });
4165
4328
  const durationInSeconds = durationNotYetApplyingPlaybackRate * playbackRate;
4166
4329
  const samples = await sampleIterator.getSamples(timeInSeconds, durationInSeconds);
4167
- audioManager.logOpenFrames();
4330
+ mediaCache.audioManager.logOpenFrames();
4168
4331
  const audioDataArray = [];
4169
4332
  for (let i = 0;i < samples.length; i++) {
4170
4333
  const sample = samples[i];
@@ -4229,10 +4392,8 @@ var extractAudioInternal = async ({
4229
4392
  throw err;
4230
4393
  }
4231
4394
  };
4232
- var queue = Promise.resolve(undefined);
4233
4395
  var extractAudio = (params) => {
4234
- queue = queue.then(() => extractAudioInternal(params));
4235
- return queue;
4396
+ return params.mediaCache.queueAudioExtraction(() => extractAudioInternal(params));
4236
4397
  };
4237
4398
 
4238
4399
  // src/video-extraction/extract-frame.ts
@@ -4248,9 +4409,10 @@ var extractFrameInternal = async ({
4248
4409
  fps,
4249
4410
  maxCacheSize,
4250
4411
  credentials,
4251
- requestInit
4412
+ requestInit,
4413
+ mediaCache
4252
4414
  }) => {
4253
- const sink = await getSink(src, logLevel, credentials, requestInit);
4415
+ const sink = await mediaCache.sinkManager.getSink(src, logLevel, credentials, requestInit);
4254
4416
  const [video, mediaDurationInSecondsRaw] = await Promise.all([
4255
4417
  sink.getVideo(),
4256
4418
  loop ? sink.getDuration() : Promise.resolve(null)
@@ -4300,7 +4462,7 @@ var extractFrameInternal = async ({
4300
4462
  };
4301
4463
  }
4302
4464
  try {
4303
- const keyframeBank = await keyframeManager.requestKeyframeBank({
4465
+ const keyframeBank = await mediaCache.keyframeManager.requestKeyframeBank({
4304
4466
  videoSampleSink: video.sampleSink,
4305
4467
  timestamp: timeInSeconds,
4306
4468
  src,
@@ -4329,10 +4491,8 @@ var extractFrameInternal = async ({
4329
4491
  return { type: "cannot-decode", durationInSeconds: mediaDurationInSeconds };
4330
4492
  }
4331
4493
  };
4332
- var queue2 = Promise.resolve(undefined);
4333
4494
  var extractFrame = (params) => {
4334
- queue2 = queue2.then(() => extractFrameInternal(params));
4335
- return queue2;
4495
+ return params.mediaCache.queueFrameExtraction(() => extractFrameInternal(params));
4336
4496
  };
4337
4497
 
4338
4498
  // src/video-extraction/rotate-frame.ts
@@ -4384,7 +4544,8 @@ var extractFrameAndAudio = async ({
4384
4544
  fps,
4385
4545
  maxCacheSize,
4386
4546
  credentials,
4387
- requestInit
4547
+ requestInit,
4548
+ mediaCache
4388
4549
  }) => {
4389
4550
  try {
4390
4551
  const [video, audio] = await Promise.all([
@@ -4399,7 +4560,8 @@ var extractFrameAndAudio = async ({
4399
4560
  fps,
4400
4561
  maxCacheSize,
4401
4562
  credentials,
4402
- requestInit
4563
+ requestInit,
4564
+ mediaCache
4403
4565
  }) : null,
4404
4566
  includeAudio ? extractAudio({
4405
4567
  src,
@@ -4414,7 +4576,8 @@ var extractFrameAndAudio = async ({
4414
4576
  trimBefore,
4415
4577
  maxCacheSize,
4416
4578
  credentials,
4417
- requestInit
4579
+ requestInit,
4580
+ mediaCache
4418
4581
  }) : null
4419
4582
  ]);
4420
4583
  if (video?.type === "cannot-decode") {
@@ -4505,7 +4668,8 @@ var addBroadcastChannelListener = () => {
4505
4668
  fps: data.fps,
4506
4669
  maxCacheSize: data.maxCacheSize,
4507
4670
  credentials: data.credentials,
4508
- requestInit: data.requestInit
4671
+ requestInit: data.requestInit,
4672
+ mediaCache: globalMediaCache
4509
4673
  });
4510
4674
  if (result.type === "cannot-decode") {
4511
4675
  const cannotDecodeResponse = {
@@ -4613,7 +4777,8 @@ var extractFrameViaBroadcastChannel = async ({
4613
4777
  fps,
4614
4778
  maxCacheSize,
4615
4779
  credentials,
4616
- requestInit
4780
+ requestInit,
4781
+ mediaCache
4617
4782
  }) => {
4618
4783
  if (isClientSideRendering || window.remotion_isMainTab) {
4619
4784
  return extractFrameAndAudio({
@@ -4631,7 +4796,8 @@ var extractFrameViaBroadcastChannel = async ({
4631
4796
  fps,
4632
4797
  maxCacheSize,
4633
4798
  credentials,
4634
- requestInit
4799
+ requestInit,
4800
+ mediaCache
4635
4801
  });
4636
4802
  }
4637
4803
  await waitForMainTabToBeReady(window.remotion_broadcastChannel);
@@ -4786,6 +4952,7 @@ var AudioForRendering = ({
4786
4952
  sequenceContext?.durationInFrames
4787
4953
  ]);
4788
4954
  const maxCacheSize = useMaxMediaCacheSize(logLevel);
4955
+ const mediaCache = useRenderMediaCache(logLevel);
4789
4956
  const audioEnabled = Internals16.useAudioEnabled();
4790
4957
  useLayoutEffect2(() => {
4791
4958
  const timestamp = frame / fps;
@@ -4825,8 +4992,12 @@ var AudioForRendering = ({
4825
4992
  fps,
4826
4993
  maxCacheSize,
4827
4994
  credentials,
4828
- requestInit: initialRequestInit
4995
+ requestInit: initialRequestInit,
4996
+ mediaCache
4829
4997
  }).then((result) => {
4998
+ if (mediaCache.isDisposed()) {
4999
+ return;
5000
+ }
4830
5001
  const handleError = (error, clientSideError, fallbackMessage) => {
4831
5002
  const [action, errorToUse] = callOnErrorAndResolve({
4832
5003
  onError,
@@ -4888,6 +5059,9 @@ var AudioForRendering = ({
4888
5059
  }
4889
5060
  continueRender(newHandle);
4890
5061
  }).catch((error) => {
5062
+ if (mediaCache.isDisposed()) {
5063
+ return;
5064
+ }
4891
5065
  cancelRender2(error);
4892
5066
  });
4893
5067
  return () => {
@@ -4924,7 +5098,8 @@ var AudioForRendering = ({
4924
5098
  audioEnabled,
4925
5099
  onError,
4926
5100
  credentials,
4927
- initialRequestInit
5101
+ initialRequestInit,
5102
+ mediaCache
4928
5103
  ]);
4929
5104
  if (replaceWithHtml5Audio) {
4930
5105
  return /* @__PURE__ */ jsx2(Html5Audio, {
@@ -5674,6 +5849,7 @@ var VideoForRendering = ({
5674
5849
  const audioEnabled = Internals21.useAudioEnabled();
5675
5850
  const videoEnabled = Internals21.useVideoEnabled();
5676
5851
  const maxCacheSize = useMaxMediaCacheSize(logLevel);
5852
+ const mediaCache = useRenderMediaCache(logLevel);
5677
5853
  const effectChainState = Internals21.useEffectChainState();
5678
5854
  const [error, setError] = useState5(null);
5679
5855
  if (error) {
@@ -5720,8 +5896,15 @@ var VideoForRendering = ({
5720
5896
  fps,
5721
5897
  maxCacheSize,
5722
5898
  credentials,
5723
- requestInit: initialRequestInit
5899
+ requestInit: initialRequestInit,
5900
+ mediaCache
5724
5901
  }).then(async (result) => {
5902
+ if (mediaCache.isDisposed()) {
5903
+ if (result.type === "success") {
5904
+ result.frame?.close();
5905
+ }
5906
+ return;
5907
+ }
5725
5908
  const handleError = (err, clientSideError, fallbackMessage, mediaDurationInSeconds) => {
5726
5909
  if (environment.isClientSideRendering) {
5727
5910
  cancelRender3(clientSideError);
@@ -5791,7 +5974,7 @@ var VideoForRendering = ({
5791
5974
  width: imageBitmap.width,
5792
5975
  height: imageBitmap.height
5793
5976
  });
5794
- if (!completed) {
5977
+ if (!completed || mediaCache.isDisposed()) {
5795
5978
  imageBitmap.close();
5796
5979
  return;
5797
5980
  }
@@ -5834,6 +6017,9 @@ var VideoForRendering = ({
5834
6017
  }
5835
6018
  continueRender(newHandle);
5836
6019
  }).catch((err) => {
6020
+ if (mediaCache.isDisposed()) {
6021
+ return;
6022
+ }
5837
6023
  cancelRender3(err);
5838
6024
  });
5839
6025
  return () => {
@@ -5876,7 +6062,8 @@ var VideoForRendering = ({
5876
6062
  credentials,
5877
6063
  effectChainState,
5878
6064
  effects,
5879
- initialRequestInit
6065
+ initialRequestInit,
6066
+ mediaCache
5880
6067
  ]);
5881
6068
  warnAboutObjectFitInStyleOrClassName({ style, className, logLevel });
5882
6069
  const classNameValue = useMemo5(() => {