molstar
Version:
A comprehensive macromolecular library.
115 lines • 6.1 kB
JavaScript
/**
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { __assign, __awaiter, __generator } from "tslib";
import * as HME from 'h264-mp4-encoder';
import { PluginStateAnimation } from '../../mol-plugin-state/animation/model';
export function encodeMp4Animation(plugin, ctx, params) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function () {
var durationMs, encoder, width, height, vw, vh, normalizedViewport, loop, canvasProps, wasAnimating, stoppedAnimation, finalized, fps, N, dt, i, image;
return __generator(this, function (_d) {
switch (_d.label) {
case 0: return [4 /*yield*/, ctx.update({ message: 'Initializing...', isIndeterminate: true })];
case 1:
_d.sent();
validateViewport(params);
durationMs = PluginStateAnimation.getDuration(plugin, params.animation);
if (durationMs === void 0) {
throw new Error('The animation does not have the duration specified.');
}
return [4 /*yield*/, HME.createH264MP4Encoder()];
case 2:
encoder = _d.sent();
width = params.width, height = params.height;
vw = params.viewport.width, vh = params.viewport.height;
// dimensions must be a multiple of 2
if (vw % 2 !== 0)
vw -= 1;
if (vh % 2 !== 0)
vh -= 1;
normalizedViewport = __assign(__assign({}, params.viewport), { width: vw, height: vh });
encoder.width = vw;
encoder.height = vh;
if (params.quantizationParameter)
encoder.quantizationParameter = params.quantizationParameter;
if (params.fps)
encoder.frameRate = params.fps;
encoder.initialize();
loop = plugin.animationLoop;
canvasProps = (_a = plugin.canvas3d) === null || _a === void 0 ? void 0 : _a.props;
wasAnimating = loop.isAnimating;
stoppedAnimation = true, finalized = false;
_d.label = 3;
case 3:
_d.trys.push([3, , 13, 16]);
loop.stop();
loop.resetTime(0);
if (params.customBackground !== void 0) {
(_b = plugin.canvas3d) === null || _b === void 0 ? void 0 : _b.setProps({ renderer: { backgroundColor: params.customBackground }, transparentBackground: false }, true);
}
fps = encoder.frameRate;
N = Math.ceil(durationMs / 1000 * fps);
dt = durationMs / N;
return [4 /*yield*/, ctx.update({ message: 'Rendering...', isIndeterminate: false, current: 0, max: N + 1 })];
case 4:
_d.sent();
return [4 /*yield*/, plugin.managers.animation.play(params.animation.definition, params.animation.params)];
case 5:
_d.sent();
stoppedAnimation = false;
i = 0;
_d.label = 6;
case 6:
if (!(i <= N)) return [3 /*break*/, 10];
return [4 /*yield*/, loop.tick(i * dt, { isSynchronous: true, manualDraw: true })];
case 7:
_d.sent();
image = params.pass.getImageData(width, height, normalizedViewport);
encoder.addFrameRgba(image.data);
if (!ctx.shouldUpdate) return [3 /*break*/, 9];
return [4 /*yield*/, ctx.update({ current: i + 1 })];
case 8:
_d.sent();
_d.label = 9;
case 9:
i++;
return [3 /*break*/, 6];
case 10: return [4 /*yield*/, ctx.update({ message: 'Applying finishing touches...', isIndeterminate: true })];
case 11:
_d.sent();
return [4 /*yield*/, plugin.managers.animation.stop()];
case 12:
_d.sent();
stoppedAnimation = true;
encoder.finalize();
finalized = true;
return [2 /*return*/, encoder.FS.readFile(encoder.outputFilename)];
case 13:
if (finalized)
encoder.delete();
if (params.customBackground !== void 0) {
(_c = plugin.canvas3d) === null || _c === void 0 ? void 0 : _c.setProps({ renderer: { backgroundColor: canvasProps === null || canvasProps === void 0 ? void 0 : canvasProps.renderer.backgroundColor }, transparentBackground: canvasProps === null || canvasProps === void 0 ? void 0 : canvasProps.transparentBackground });
}
if (!!stoppedAnimation) return [3 /*break*/, 15];
return [4 /*yield*/, plugin.managers.animation.stop()];
case 14:
_d.sent();
_d.label = 15;
case 15:
if (wasAnimating)
loop.start();
return [7 /*endfinally*/];
case 16: return [2 /*return*/];
}
});
});
}
function validateViewport(params) {
if (params.viewport.x + params.viewport.width > params.width || params.viewport.y + params.viewport.height > params.height) {
throw new Error('Viewport exceeds the canvas dimensions.');
}
}
//# sourceMappingURL=encoder.js.map