mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-02 13:23:51 +02:00
Fixed doubly stacked rotation correction when converting rotated video with a custom process function (fixes #218)
This commit is contained in:
+9
-6
@@ -48,6 +48,7 @@
|
|||||||
target
|
target
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let ctx = null;
|
||||||
const conversion = await Mediabunny.Conversion.init({
|
const conversion = await Mediabunny.Conversion.init({
|
||||||
input: new Mediabunny.Input({
|
input: new Mediabunny.Input({
|
||||||
formats: Mediabunny.ALL_FORMATS,
|
formats: Mediabunny.ALL_FORMATS,
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
output,
|
output,
|
||||||
audio: (_, n) => ({
|
audio: (_, n) => ({
|
||||||
discard: n > 1,
|
discard: n > 1,
|
||||||
|
//codec: 'opus',
|
||||||
/*
|
/*
|
||||||
process: (sample) => {
|
process: (sample) => {
|
||||||
return sample;
|
return sample;
|
||||||
@@ -97,7 +99,7 @@
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
video: () => ({
|
video: () => ({
|
||||||
/*
|
//discard: true,
|
||||||
process: (sample) => {
|
process: (sample) => {
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
// Create a canvas for image compositing
|
// Create a canvas for image compositing
|
||||||
@@ -108,13 +110,14 @@
|
|||||||
ctx = canvas.getContext('2d');
|
ctx = canvas.getContext('2d');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(ctx.canvas.width, ctx.canvas.height);
|
||||||
|
|
||||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||||
sample.draw(ctx, 0, 0);
|
sample.drawWithFit(ctx, { fit: 'fill' });
|
||||||
ctx.drawImage(watermark, 32, 32);
|
//ctx.drawImage(watermark, 32, 32);
|
||||||
|
|
||||||
return ctx.canvas;
|
return ctx.canvas;
|
||||||
},
|
},
|
||||||
*/
|
|
||||||
//width: 300,
|
//width: 300,
|
||||||
//alpha: 'keep',
|
//alpha: 'keep',
|
||||||
//width: 320,
|
//width: 320,
|
||||||
@@ -170,8 +173,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
trim: {
|
trim: {
|
||||||
start: 0,
|
//start: 0,
|
||||||
end: 10
|
//end: 10
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log(conversion);
|
console.log(conversion);
|
||||||
|
|||||||
+6
-2
@@ -182,7 +182,8 @@ export type ConversionVideoOptions = {
|
|||||||
* corrections.
|
* corrections.
|
||||||
*
|
*
|
||||||
* Must return a {@link VideoSample} or a `CanvasImageSource`, an array of them, or `null` for dropping the frame.
|
* Must return a {@link VideoSample} or a `CanvasImageSource`, an array of them, or `null` for dropping the frame.
|
||||||
* When non-timestamped data is returned, the timestamp and duration from the source sample will be used.
|
* When non-timestamped data is returned, the timestamp and duration from the source sample will be used. Rotation
|
||||||
|
* metadata of the returned sample will be ignored.
|
||||||
*
|
*
|
||||||
* This function can also be used to manually resize frames. When doing so, you should signal the post-process
|
* This function can also be used to manually resize frames. When doing so, you should signal the post-process
|
||||||
* dimensions using the `processedWidth` and `processedHeight` fields, which enables the encoder to better know what
|
* dimensions using the `processedWidth` and `processedHeight` fields, which enables the encoder to better know what
|
||||||
@@ -873,7 +874,10 @@ export class Conversion {
|
|||||||
|| trackOptions.process !== undefined;
|
|| trackOptions.process !== undefined;
|
||||||
let needsRerender = width !== originalWidth
|
let needsRerender = width !== originalWidth
|
||||||
|| height !== originalHeight
|
|| height !== originalHeight
|
||||||
|| (totalRotation !== 0 && !outputSupportsRotation)
|
// TODO This is suboptimal: Forcing a rerender when both rotation and process are set is not
|
||||||
|
// performance-optimal, but right now there's no other way because we can't change the track rotation
|
||||||
|
// metadata after the output has already started. Should be possible with API changes in v2, though!
|
||||||
|
|| (totalRotation !== 0 && (!outputSupportsRotation || trackOptions.process !== undefined))
|
||||||
|| !!crop;
|
|| !!crop;
|
||||||
|
|
||||||
const alpha = trackOptions.alpha ?? 'discard';
|
const alpha = trackOptions.alpha ?? 'discard';
|
||||||
|
|||||||
+4
-1
@@ -552,7 +552,6 @@ export class VideoSample implements Disposable {
|
|||||||
dHeight,
|
dHeight,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Restore the previous transformation state
|
|
||||||
context.restore();
|
context.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,6 +643,8 @@ export class VideoSample implements Disposable {
|
|||||||
dy = (canvasHeight - newHeight) / 2;
|
dy = (canvasHeight - newHeight) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.save();
|
||||||
|
|
||||||
const aspectRatioChange = rotation % 180 === 0 ? 1 : newWidth / newHeight;
|
const aspectRatioChange = rotation % 180 === 0 ? 1 : newWidth / newHeight;
|
||||||
context.translate(canvasWidth / 2, canvasHeight / 2);
|
context.translate(canvasWidth / 2, canvasHeight / 2);
|
||||||
context.rotate(rotation * Math.PI / 180);
|
context.rotate(rotation * Math.PI / 180);
|
||||||
@@ -655,6 +656,8 @@ export class VideoSample implements Disposable {
|
|||||||
// Important that we don't use .draw() here since that would take rotation into account, but we wanna handle it
|
// Important that we don't use .draw() here since that would take rotation into account, but we wanna handle it
|
||||||
// ourselves here
|
// ourselves here
|
||||||
context.drawImage(this.toCanvasImageSource(), sx, sy, sWidth, sHeight, dx, dy, newWidth, newHeight);
|
context.drawImage(this.toCanvasImageSource(), sx, sy, sWidth, sHeight, dx, dy, newWidth, newHeight);
|
||||||
|
|
||||||
|
context.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
|
|||||||
Reference in New Issue
Block a user