mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-28 19:33:51 +02:00
Update thumbnail generation example to use cursors
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Input, ALL_FORMATS, BlobSource, UrlSource, CanvasSink } from 'mediabunny';
|
||||
import { Input, ALL_FORMATS, BlobSource, UrlSource, VideoSampleCursor } from 'mediabunny';
|
||||
|
||||
import SampleFileUrl from '../../docs/assets/big-buck-bunny-trimmed.mp4';
|
||||
import { canvasTransformer } from '../../src/cursors.js';
|
||||
(document.querySelector('#sample-file-download') as HTMLAnchorElement).href = SampleFileUrl;
|
||||
|
||||
const selectMediaButton = document.querySelector('#select-file') as HTMLButtonElement;
|
||||
@@ -69,16 +70,23 @@ const generateThumbnails = async (resource: File | string) => {
|
||||
(_, i) => firstTimestamp + i * (lastTimestamp - firstTimestamp) / THUMBNAIL_COUNT,
|
||||
);
|
||||
|
||||
// Create a CanvasSink for extracting resized frames from the video track
|
||||
const sink = new CanvasSink(videoTrack, {
|
||||
width: Math.floor(width * window.devicePixelRatio),
|
||||
height: Math.floor(height * window.devicePixelRatio),
|
||||
fit: 'fill',
|
||||
// Create a cursor to extract frames from the video
|
||||
const cursor = new VideoSampleCursor(videoTrack, {
|
||||
transform: canvasTransformer({
|
||||
width: Math.floor(width * window.devicePixelRatio),
|
||||
height: Math.floor(height * window.devicePixelRatio),
|
||||
fit: 'fill',
|
||||
}),
|
||||
});
|
||||
|
||||
// Queue all cursor commands at once, including closing the cursor; this allows it to optimize access patterns
|
||||
const promises = timestamps.map(x => cursor.seekTo(x));
|
||||
void cursor.close();
|
||||
|
||||
// Iterate over all thumbnail canvases
|
||||
let i = 0;
|
||||
for await (const wrappedCanvas of sink.canvasesAtTimestamps(timestamps)) {
|
||||
for (const promise of promises) {
|
||||
const wrappedCanvas = await promise;
|
||||
const container = thumbnailElements[i]!;
|
||||
|
||||
if (wrappedCanvas) {
|
||||
|
||||
+1
-1
@@ -930,7 +930,6 @@ export abstract class SampleCursor<
|
||||
this._lastPendingRequest = pendingRequest;
|
||||
|
||||
this._pumpGate.open();
|
||||
|
||||
deferred.execute(); // Waiting for the return would be too long
|
||||
|
||||
return res.set(await request.promise);
|
||||
@@ -987,6 +986,7 @@ export abstract class SampleCursor<
|
||||
}
|
||||
this._lastPendingRequest = pendingRequest;
|
||||
|
||||
this._pumpGate.open();
|
||||
lock.release(); // Waiting for the return would be too long
|
||||
|
||||
return res.set(await request.promise);
|
||||
|
||||
@@ -2368,7 +2368,10 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
|
||||
}
|
||||
|
||||
async getFirstTimestamp() {
|
||||
const firstPacket = await this.getFirstPacket({ metadataOnly: true });
|
||||
const result = new ResultValue<EncodedPacket | null>();
|
||||
await this.getFirstPacket(result, { metadataOnly: true });
|
||||
|
||||
const firstPacket = result.value;
|
||||
return firstPacket?.timestamp ?? 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user