avbridge 2.11.0 → 2.12.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/CHANGELOG.md +35 -0
- package/dist/{avi-B5CQYB7L.cjs → avi-EQE6AR75.cjs} +4 -4
- package/dist/{avi-2ILLBNPQ.cjs.map → avi-EQE6AR75.cjs.map} +1 -1
- package/dist/{avi-RWWPN2PR.js → avi-NNHH4AAA.js} +3 -3
- package/dist/{avi-JXU4GQL2.js.map → avi-NNHH4AAA.js.map} +1 -1
- package/dist/{avi-JXU4GQL2.js → avi-S7EY54YA.js} +3 -3
- package/dist/{avi-RWWPN2PR.js.map → avi-S7EY54YA.js.map} +1 -1
- package/dist/{avi-2ILLBNPQ.cjs → avi-Y3N325WZ.cjs} +4 -4
- package/dist/{avi-B5CQYB7L.cjs.map → avi-Y3N325WZ.cjs.map} +1 -1
- package/dist/{chunk-GYIJU44C.js → chunk-2LNXMGT6.js} +5 -5
- package/dist/{chunk-GYIJU44C.js.map → chunk-2LNXMGT6.js.map} +1 -1
- package/dist/{chunk-DCSOQH2N.js → chunk-3AI5WFFN.js} +40 -16
- package/dist/chunk-3AI5WFFN.js.map +1 -0
- package/dist/{chunk-2NSOOMXW.js → chunk-3YKWU4FM.js} +3 -3
- package/dist/{chunk-2NSOOMXW.js.map → chunk-3YKWU4FM.js.map} +1 -1
- package/dist/{chunk-CL6UEUQF.js → chunk-5Y5BTB5D.js} +5 -5
- package/dist/{chunk-CL6UEUQF.js.map → chunk-5Y5BTB5D.js.map} +1 -1
- package/dist/{chunk-37UOSAVI.cjs → chunk-7EF4VTUS.cjs} +23 -23
- package/dist/{chunk-IHNHHEA2.js.map → chunk-7EF4VTUS.cjs.map} +1 -1
- package/dist/{chunk-OTFS7DC4.cjs → chunk-GJBNLPGI.cjs} +14 -14
- package/dist/{chunk-OTFS7DC4.cjs.map → chunk-GJBNLPGI.cjs.map} +1 -1
- package/dist/{chunk-BYGZN4Z5.cjs → chunk-HBHSUGNI.cjs} +5 -5
- package/dist/{chunk-BYGZN4Z5.cjs.map → chunk-HBHSUGNI.cjs.map} +1 -1
- package/dist/{chunk-L7A3ECI2.cjs → chunk-HZUVMXBN.cjs} +4 -4
- package/dist/{chunk-L7A3ECI2.cjs.map → chunk-HZUVMXBN.cjs.map} +1 -1
- package/dist/{chunk-Z33SBWL5.cjs → chunk-YPZFGJV3.cjs} +40 -16
- package/dist/chunk-YPZFGJV3.cjs.map +1 -0
- package/dist/{chunk-IHNHHEA2.js → chunk-Z26PXRUY.js} +9 -9
- package/dist/chunk-Z26PXRUY.js.map +1 -0
- package/dist/element-browser.js +42 -18
- package/dist/element-browser.js.map +1 -1
- package/dist/element.cjs +5 -5
- package/dist/element.d.cts +1 -1
- package/dist/element.d.ts +1 -1
- package/dist/element.js +4 -4
- package/dist/index.cjs +21 -21
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +9 -9
- package/dist/{libav-demux-3N5Y3VQA.cjs → libav-demux-575OYCT2.cjs} +9 -9
- package/dist/{libav-demux-3N5Y3VQA.cjs.map → libav-demux-575OYCT2.cjs.map} +1 -1
- package/dist/{libav-demux-JXD4OTLM.js → libav-demux-SXZDLC7W.js} +4 -4
- package/dist/{libav-demux-JXD4OTLM.js.map → libav-demux-SXZDLC7W.js.map} +1 -1
- package/dist/libav-http-reader-2S5HAHW4.js +3 -0
- package/dist/{libav-http-reader-WXG3Z7AI.js.map → libav-http-reader-2S5HAHW4.js.map} +1 -1
- package/dist/libav-http-reader-Q356EO2K.cjs +16 -0
- package/dist/{libav-http-reader-AZLE7YFS.cjs.map → libav-http-reader-Q356EO2K.cjs.map} +1 -1
- package/dist/{player-DDdNVFDv.d.cts → player-bQ6n4hVp.d.cts} +15 -0
- package/dist/{player-DDdNVFDv.d.ts → player-bQ6n4hVp.d.ts} +15 -0
- package/dist/player.cjs +60 -15
- package/dist/player.cjs.map +1 -1
- package/dist/player.d.cts +21 -0
- package/dist/player.d.ts +21 -0
- package/dist/player.js +60 -15
- package/dist/player.js.map +1 -1
- package/dist/remux-7TA4FKTY.js +10 -0
- package/dist/{remux-56V7LDAD.js.map → remux-7TA4FKTY.js.map} +1 -1
- package/dist/remux-VPKCLHHM.cjs +35 -0
- package/dist/{remux-KUS5GIL6.cjs.map → remux-VPKCLHHM.cjs.map} +1 -1
- package/package.json +1 -1
- package/src/element/avbridge-player.ts +36 -8
- package/src/element/player-styles.ts +13 -1
- package/src/player.ts +3 -3
- package/src/types.ts +15 -0
- package/src/util/libav-http-reader.ts +58 -19
- package/dist/chunk-37UOSAVI.cjs.map +0 -1
- package/dist/chunk-DCSOQH2N.js.map +0 -1
- package/dist/chunk-Z33SBWL5.cjs.map +0 -1
- package/dist/libav-http-reader-AZLE7YFS.cjs +0 -16
- package/dist/libav-http-reader-WXG3Z7AI.js +0 -3
- package/dist/remux-56V7LDAD.js +0 -10
- package/dist/remux-KUS5GIL6.cjs +0 -35
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { createOutputFormat, generateFilename, mimeForFormat, remux, validateRemuxEligibility } from './chunk-5Y5BTB5D.js';
|
|
2
|
+
import './chunk-2LNXMGT6.js';
|
|
3
|
+
import './chunk-CPJLFFCC.js';
|
|
4
|
+
import './chunk-LUFA47FP.js';
|
|
5
|
+
import './chunk-3YKWU4FM.js';
|
|
6
|
+
import './chunk-3AI5WFFN.js';
|
|
7
|
+
import './chunk-5DMTJVIU.js';
|
|
8
|
+
import './chunk-5YAWWKA3.js';
|
|
9
|
+
//# sourceMappingURL=remux-7TA4FKTY.js.map
|
|
10
|
+
//# sourceMappingURL=remux-7TA4FKTY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"remux-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"remux-7TA4FKTY.js"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkGJBNLPGI_cjs = require('./chunk-GJBNLPGI.cjs');
|
|
4
|
+
require('./chunk-HBHSUGNI.cjs');
|
|
5
|
+
require('./chunk-2IJ66NTD.cjs');
|
|
6
|
+
require('./chunk-QDJLQR53.cjs');
|
|
7
|
+
require('./chunk-HZUVMXBN.cjs');
|
|
8
|
+
require('./chunk-YPZFGJV3.cjs');
|
|
9
|
+
require('./chunk-G4APZMCP.cjs');
|
|
10
|
+
require('./chunk-F3LQJKXK.cjs');
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Object.defineProperty(exports, "createOutputFormat", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return chunkGJBNLPGI_cjs.createOutputFormat; }
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "generateFilename", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () { return chunkGJBNLPGI_cjs.generateFilename; }
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(exports, "mimeForFormat", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function () { return chunkGJBNLPGI_cjs.mimeForFormat; }
|
|
25
|
+
});
|
|
26
|
+
Object.defineProperty(exports, "remux", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get: function () { return chunkGJBNLPGI_cjs.remux; }
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "validateRemuxEligibility", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () { return chunkGJBNLPGI_cjs.validateRemuxEligibility; }
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=remux-VPKCLHHM.cjs.map
|
|
35
|
+
//# sourceMappingURL=remux-VPKCLHHM.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"remux-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"remux-VPKCLHHM.cjs"}
|
package/package.json
CHANGED
|
@@ -247,6 +247,11 @@ export class AvbridgePlayerElement extends HTMLElement {
|
|
|
247
247
|
on(this._video, "ended", () => this._setState("ended"));
|
|
248
248
|
on(this._video, "error", () => this._setState("error"));
|
|
249
249
|
on(this._video, "timeupdate", () => this._updateTime());
|
|
250
|
+
// `progress` fires as the inner element's buffered ranges grow — keep the
|
|
251
|
+
// seek bar's buffered indicator fresh even when paused or filling ahead
|
|
252
|
+
// without timeupdate advancing. `<avbridge-video>` dispatches this on
|
|
253
|
+
// all strategies (including the synthesized ranges for canvas strategies).
|
|
254
|
+
on(this._video, "progress", () => this._updateBuffered());
|
|
250
255
|
on(this._video, "volumechange", () => this._updateVolume());
|
|
251
256
|
// Strategy changes are visible in Stats for Nerds.
|
|
252
257
|
on(this._video, "trackschange", () => this._buildSettingsMenu());
|
|
@@ -524,15 +529,38 @@ export class AvbridgePlayerElement extends HTMLElement {
|
|
|
524
529
|
this._seekInput.value = String(t);
|
|
525
530
|
this._updateSeekVisuals(t);
|
|
526
531
|
this._timeDisplay.textContent = `${formatTime(t)} / ${formatTime(d)}`;
|
|
532
|
+
this._updateBuffered();
|
|
533
|
+
}
|
|
527
534
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
535
|
+
/**
|
|
536
|
+
* Render every buffered range as its own segment so gaps (common on MSE
|
|
537
|
+
* after seeks) are visible. Not gated by `_userSeeking` — ranges should
|
|
538
|
+
* keep updating while the user scrubs, and runs cheaply on `progress`.
|
|
539
|
+
*/
|
|
540
|
+
private _updateBuffered(): void {
|
|
541
|
+
const d = this._video.duration;
|
|
542
|
+
if (!(d > 0)) return;
|
|
543
|
+
let buf: TimeRanges;
|
|
544
|
+
try { buf = this._video.buffered; } catch { return; }
|
|
545
|
+
const count = buf ? buf.length : 0;
|
|
546
|
+
const host = this._seekBuffered;
|
|
547
|
+
// Reconcile child count. Segment divs are styled via .avp-seek-buffered-range.
|
|
548
|
+
while (host.childElementCount > count) host.lastElementChild!.remove();
|
|
549
|
+
while (host.childElementCount < count) {
|
|
550
|
+
const seg = document.createElement("div");
|
|
551
|
+
seg.className = "avp-seek-buffered-range";
|
|
552
|
+
host.appendChild(seg);
|
|
553
|
+
}
|
|
554
|
+
for (let i = 0; i < count; i++) {
|
|
555
|
+
let start: number; let end: number;
|
|
556
|
+
try { start = buf.start(i); end = buf.end(i); } catch { continue; }
|
|
557
|
+
const s = Math.max(0, start);
|
|
558
|
+
const e = Math.min(d, end);
|
|
559
|
+
if (e <= s) continue;
|
|
560
|
+
const seg = host.children[i] as HTMLElement;
|
|
561
|
+
seg.style.left = `${(s / d) * 100}%`;
|
|
562
|
+
seg.style.width = `${((e - s) / d) * 100}%`;
|
|
563
|
+
}
|
|
536
564
|
}
|
|
537
565
|
|
|
538
566
|
// ── Controls: volume ───────────────────────────────────────────────────
|
|
@@ -286,6 +286,12 @@ export const PLAYER_STYLES = /* css */ `
|
|
|
286
286
|
display: flex;
|
|
287
287
|
align-items: center;
|
|
288
288
|
cursor: pointer;
|
|
289
|
+
/* Claim all touch gestures on the seek bar. Without this, Android
|
|
290
|
+
* browsers (Chrome, Samsung Internet) treat horizontal drags as
|
|
291
|
+
* scroll candidates and cancel pointermove once the gesture
|
|
292
|
+
* resolves, breaking scrub. touch-action must be set in CSS —
|
|
293
|
+
* preventDefault() on pointerdown is too late. */
|
|
294
|
+
touch-action: none;
|
|
289
295
|
}
|
|
290
296
|
|
|
291
297
|
.avp-seek-track {
|
|
@@ -303,7 +309,13 @@ export const PLAYER_STYLES = /* css */ `
|
|
|
303
309
|
|
|
304
310
|
.avp-seek-buffered {
|
|
305
311
|
position: absolute;
|
|
306
|
-
|
|
312
|
+
inset: 0;
|
|
313
|
+
pointer-events: none;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.avp-seek-buffered-range {
|
|
317
|
+
position: absolute;
|
|
318
|
+
top: 0;
|
|
307
319
|
height: 100%;
|
|
308
320
|
background: rgba(255, 255, 255, 0.35);
|
|
309
321
|
border-radius: inherit;
|
package/src/player.ts
CHANGED
|
@@ -132,9 +132,9 @@ export class UnifiedPlayer {
|
|
|
132
132
|
private readonly options: CreatePlayerOptions,
|
|
133
133
|
private readonly registry: PluginRegistry,
|
|
134
134
|
) {
|
|
135
|
-
const { requestInit, fetchFn } = options;
|
|
136
|
-
if (requestInit || fetchFn) {
|
|
137
|
-
this.transport = { requestInit, fetchFn };
|
|
135
|
+
const { requestInit, fetchFn, cacheBytes } = options;
|
|
136
|
+
if (requestInit || fetchFn || cacheBytes !== undefined) {
|
|
137
|
+
this.transport = { requestInit, fetchFn, cacheBytes };
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
package/src/types.ts
CHANGED
|
@@ -287,6 +287,14 @@ export interface CreatePlayerOptions {
|
|
|
287
287
|
* for interceptors, logging, or environments without a global fetch.
|
|
288
288
|
*/
|
|
289
289
|
fetchFn?: FetchFn;
|
|
290
|
+
/**
|
|
291
|
+
* Byte budget for the libav HTTP reader's LRU cache of fetched ranges.
|
|
292
|
+
* Defaults to 8 MB. Set to `0` to disable caching. Raise this when the
|
|
293
|
+
* app plays seek-heavy legacy-container media from URLs — hot regions
|
|
294
|
+
* (header/moov, tail index, current window) stay resident instead of
|
|
295
|
+
* being re-fetched on every bounce.
|
|
296
|
+
*/
|
|
297
|
+
cacheBytes?: number;
|
|
290
298
|
}
|
|
291
299
|
|
|
292
300
|
/** Signature-compatible with `globalThis.fetch`. */
|
|
@@ -296,6 +304,13 @@ export type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<
|
|
|
296
304
|
export interface TransportConfig {
|
|
297
305
|
requestInit?: RequestInit;
|
|
298
306
|
fetchFn?: FetchFn;
|
|
307
|
+
/**
|
|
308
|
+
* Byte budget for the libav HTTP reader's LRU cache of fetched ranges.
|
|
309
|
+
* Defaults to 8 MB. Set to `0` to disable caching entirely. Higher
|
|
310
|
+
* values help seek-heavy network playback keep hot regions
|
|
311
|
+
* (header/moov, tail index, current read) resident.
|
|
312
|
+
*/
|
|
313
|
+
cacheBytes?: number;
|
|
299
314
|
}
|
|
300
315
|
|
|
301
316
|
/** Events emitted by {@link UnifiedPlayer}. Strongly typed. */
|
|
@@ -32,8 +32,13 @@
|
|
|
32
32
|
* clamped to `[256 KB, 1 MB]`. Small reads get amortized; pathological
|
|
33
33
|
* large requests don't OOM us.
|
|
34
34
|
*
|
|
35
|
-
* - **
|
|
36
|
-
*
|
|
35
|
+
* - **LRU block cache.** Fetched blocks are kept in a Map keyed by start
|
|
36
|
+
* position, bounded by a byte budget (default 8 MB, configurable via
|
|
37
|
+
* `cacheBytes`). Map insertion order doubles as recency; re-accessing
|
|
38
|
+
* a block promotes it via delete+set. Eviction walks oldest-first
|
|
39
|
+
* until total bytes fit the budget. Typical seek pattern has three
|
|
40
|
+
* hot regions — header/moov at the front, index at the tail, current
|
|
41
|
+
* read position — all of which fit comfortably under the default.
|
|
37
42
|
*
|
|
38
43
|
* - **Safe detach.** `detach()` clears `libav.onblockread`, sets a
|
|
39
44
|
* destroyed flag, and ignores any in-flight fetch resolutions so we
|
|
@@ -42,6 +47,7 @@
|
|
|
42
47
|
|
|
43
48
|
const MIN_READ = 256 * 1024;
|
|
44
49
|
const MAX_READ = 1 * 1024 * 1024;
|
|
50
|
+
const DEFAULT_CACHE_BYTES = 8 * 1024 * 1024;
|
|
45
51
|
|
|
46
52
|
interface LibavLike {
|
|
47
53
|
mkblockreaderdev(name: string, size: number): Promise<void>;
|
|
@@ -69,6 +75,12 @@ export interface AttachLibavHttpReaderOptions {
|
|
|
69
75
|
requestInit?: RequestInit;
|
|
70
76
|
/** Override fetch (for testing). Defaults to globalThis.fetch. */
|
|
71
77
|
fetchFn?: typeof fetch;
|
|
78
|
+
/**
|
|
79
|
+
* Byte budget for the LRU block cache. Defaults to 8 MB. Set to `0`
|
|
80
|
+
* to disable caching. Raise this (e.g. 32 MB) for apps that play
|
|
81
|
+
* seek-heavy legacy-container media over the network.
|
|
82
|
+
*/
|
|
83
|
+
cacheBytes?: number;
|
|
72
84
|
}
|
|
73
85
|
|
|
74
86
|
/**
|
|
@@ -108,6 +120,7 @@ export async function prepareLibavInput(
|
|
|
108
120
|
const handle = await attachLibavHttpReader(libav, filename, source.url, {
|
|
109
121
|
requestInit: transport?.requestInit,
|
|
110
122
|
fetchFn: transport?.fetchFn,
|
|
123
|
+
cacheBytes: transport?.cacheBytes,
|
|
111
124
|
});
|
|
112
125
|
return {
|
|
113
126
|
filename,
|
|
@@ -192,9 +205,12 @@ export async function attachLibavHttpReader(
|
|
|
192
205
|
// ── State ───────────────────────────────────────────────────────────────
|
|
193
206
|
|
|
194
207
|
let detached = false;
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
|
|
208
|
+
// LRU cache of fetched blocks, keyed by start position. Map insertion
|
|
209
|
+
// order = recency. Bounded by `cacheBudget` bytes; evicts oldest-first
|
|
210
|
+
// on overflow. Set budget to 0 to disable caching.
|
|
211
|
+
const cache = new Map<number, Uint8Array>();
|
|
212
|
+
let cacheBytes = 0;
|
|
213
|
+
const cacheBudget = Math.max(0, options.cacheBytes ?? DEFAULT_CACHE_BYTES);
|
|
198
214
|
// The currently in-flight fetch, if any. Used both for serialization
|
|
199
215
|
// (we await this before starting another) and for in-flight dedup.
|
|
200
216
|
let inflight: Promise<void> | null = null;
|
|
@@ -206,17 +222,39 @@ export async function attachLibavHttpReader(
|
|
|
206
222
|
return doubled;
|
|
207
223
|
}
|
|
208
224
|
|
|
209
|
-
/**
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
225
|
+
/**
|
|
226
|
+
* Look up a cached block that fully covers `[pos, pos+length)`. On hit,
|
|
227
|
+
* promote the block to most-recent and return the slice. On miss, null.
|
|
228
|
+
*/
|
|
229
|
+
function cacheLookup(pos: number, length: number): Uint8Array | null {
|
|
230
|
+
for (const [blockPos, bytes] of cache) {
|
|
231
|
+
if (pos >= blockPos && pos + length <= blockPos + bytes.byteLength) {
|
|
232
|
+
cache.delete(blockPos);
|
|
233
|
+
cache.set(blockPos, bytes);
|
|
234
|
+
const offset = pos - blockPos;
|
|
235
|
+
return bytes.subarray(offset, offset + length);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return null;
|
|
213
239
|
}
|
|
214
240
|
|
|
215
|
-
/**
|
|
216
|
-
function
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
241
|
+
/** Insert a fetched block; evict least-recently-used until under budget. */
|
|
242
|
+
function cacheInsert(pos: number, bytes: Uint8Array): void {
|
|
243
|
+
const existing = cache.get(pos);
|
|
244
|
+
if (existing) {
|
|
245
|
+
cacheBytes -= existing.byteLength;
|
|
246
|
+
cache.delete(pos);
|
|
247
|
+
}
|
|
248
|
+
cache.set(pos, bytes);
|
|
249
|
+
cacheBytes += bytes.byteLength;
|
|
250
|
+
while (cacheBytes > cacheBudget && cache.size > 0) {
|
|
251
|
+
const oldestKey = cache.keys().next().value as number | undefined;
|
|
252
|
+
if (oldestKey === undefined) break;
|
|
253
|
+
const oldest = cache.get(oldestKey);
|
|
254
|
+
if (!oldest) break;
|
|
255
|
+
cache.delete(oldestKey);
|
|
256
|
+
cacheBytes -= oldest.byteLength;
|
|
257
|
+
}
|
|
220
258
|
}
|
|
221
259
|
|
|
222
260
|
/** Fetch one Range and update the cache. */
|
|
@@ -235,7 +273,7 @@ export async function attachLibavHttpReader(
|
|
|
235
273
|
);
|
|
236
274
|
}
|
|
237
275
|
const buf = new Uint8Array(await res.arrayBuffer());
|
|
238
|
-
|
|
276
|
+
cacheInsert(pos, buf);
|
|
239
277
|
return buf;
|
|
240
278
|
}
|
|
241
279
|
|
|
@@ -252,9 +290,9 @@ export async function attachLibavHttpReader(
|
|
|
252
290
|
if (detached) return;
|
|
253
291
|
|
|
254
292
|
// Cache hit — reply directly without a network round-trip.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
try { await libav.ff_block_reader_dev_send(name, pos,
|
|
293
|
+
const hit = cacheLookup(pos, length);
|
|
294
|
+
if (hit) {
|
|
295
|
+
try { await libav.ff_block_reader_dev_send(name, pos, hit); } catch { /* ignore — libav may have torn down */ }
|
|
258
296
|
return;
|
|
259
297
|
}
|
|
260
298
|
|
|
@@ -312,7 +350,8 @@ export async function attachLibavHttpReader(
|
|
|
312
350
|
try { await inflight; } catch { /* ignore */ }
|
|
313
351
|
}
|
|
314
352
|
// Drop the cache and unlink the virtual file.
|
|
315
|
-
|
|
353
|
+
cache.clear();
|
|
354
|
+
cacheBytes = 0;
|
|
316
355
|
try { await libav.unlinkreadaheadfile(filename); } catch { /* ignore */ }
|
|
317
356
|
},
|
|
318
357
|
};
|