@revideo/ffmpeg 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 motion-canvas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,44 @@
1
+ import type { AssetInfo, MetaField, Project, RendererResult, RendererSettings } from '@revideo/core';
2
+ import { Exporter } from '@revideo/core';
3
+ /**
4
+ * FFmpeg video exporter.
5
+ *
6
+ * @remarks
7
+ * Most of the export logic is handled on the server. This class communicates
8
+ * with the FFmpegBridge through a WebSocket connection which lets it invoke
9
+ * methods on the FFmpegExporterServer class.
10
+ *
11
+ * For example, calling the following method:
12
+ * ```ts
13
+ * async this.invoke('process', 7);
14
+ * ```
15
+ * Will invoke the `process` method on the FFmpegExporterServer class with `7`
16
+ * as the argument. The result of the method will be returned as a Promise.
17
+ *
18
+ * Before any methods can be invoked, the FFmpegExporterServer class must be
19
+ * initialized by invoking `start`.
20
+ */
21
+ export declare class FFmpegExporterClient implements Exporter {
22
+ private readonly project;
23
+ private readonly settings;
24
+ static readonly id = "@revideo/ffmpeg";
25
+ static readonly displayName = "Video (FFmpeg)";
26
+ static meta(project: Project): MetaField<any>;
27
+ static create(project: Project, settings: RendererSettings): Promise<FFmpegExporterClient>;
28
+ private static readonly response;
29
+ constructor(project: Project, settings: RendererSettings);
30
+ start(): Promise<void>;
31
+ handleFrame(canvas: HTMLCanvasElement): Promise<void>;
32
+ stop(result: RendererResult): Promise<void>;
33
+ kill(): Promise<void>;
34
+ generateAudio(assets: AssetInfo[][], endFrame: number): Promise<void>;
35
+ /**
36
+ * Remotely invoke a method on the server and wait for a response.
37
+ *
38
+ * @param method - The method name to execute on the server.
39
+ * @param data - The data that will be passed as an argument to the method.
40
+ * Should be serializable.
41
+ */
42
+ private invoke;
43
+ }
44
+ //# sourceMappingURL=FFmpegExporterClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FFmpegExporterClient.d.ts","sourceRoot":"","sources":["../../client/FFmpegExporterClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,OAAO,EACP,cAAc,EACd,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAGL,QAAQ,EAGT,MAAM,eAAe,CAAC;AAkBvB;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,oBAAqB,YAAW,QAAQ;IA4BjD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IA5B3B,gBAAuB,EAAE,qBAAqB;IAC9C,gBAAuB,WAAW,oBAAoB;WAExC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC;WAShC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB;IAIvE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAyC;gBAWtD,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,gBAAgB;IAGhC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrD,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,aAAa,CACxB,MAAM,EAAE,SAAS,EAAE,EAAE,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAIhB;;;;;;OAMG;IACH,OAAO,CAAC,MAAM;CA6Bf"}
@@ -0,0 +1,102 @@
1
+ var _a;
2
+ import { BoolMetaField, EventDispatcher, ObjectMetaField, } from '@revideo/core';
3
+ /**
4
+ * FFmpeg video exporter.
5
+ *
6
+ * @remarks
7
+ * Most of the export logic is handled on the server. This class communicates
8
+ * with the FFmpegBridge through a WebSocket connection which lets it invoke
9
+ * methods on the FFmpegExporterServer class.
10
+ *
11
+ * For example, calling the following method:
12
+ * ```ts
13
+ * async this.invoke('process', 7);
14
+ * ```
15
+ * Will invoke the `process` method on the FFmpegExporterServer class with `7`
16
+ * as the argument. The result of the method will be returned as a Promise.
17
+ *
18
+ * Before any methods can be invoked, the FFmpegExporterServer class must be
19
+ * initialized by invoking `start`.
20
+ */
21
+ export class FFmpegExporterClient {
22
+ static meta(project) {
23
+ return new ObjectMetaField(this.displayName, {
24
+ fastStart: new BoolMetaField('fast start', true),
25
+ includeAudio: new BoolMetaField('include audio', true).disable(!project.audio),
26
+ });
27
+ }
28
+ static async create(project, settings) {
29
+ return new _a(project, settings);
30
+ }
31
+ constructor(project, settings) {
32
+ this.project = project;
33
+ this.settings = settings;
34
+ }
35
+ async start() {
36
+ const options = this.settings.exporter.options;
37
+ await this.invoke('start', {
38
+ ...this.settings,
39
+ ...options,
40
+ audio: this.project.audio,
41
+ audioOffset: this.project.meta.shared.audioOffset.get() - this.settings.range[0],
42
+ });
43
+ }
44
+ async handleFrame(canvas) {
45
+ await this.invoke('handleFrame', {
46
+ data: canvas.toDataURL('image/png'),
47
+ });
48
+ }
49
+ async stop(result) {
50
+ await this.invoke('end', result);
51
+ }
52
+ async kill() {
53
+ await this.invoke('kill', {});
54
+ }
55
+ async generateAudio(assets, endFrame) {
56
+ await this.invoke('generateAudio', { assets, endFrame });
57
+ }
58
+ /**
59
+ * Remotely invoke a method on the server and wait for a response.
60
+ *
61
+ * @param method - The method name to execute on the server.
62
+ * @param data - The data that will be passed as an argument to the method.
63
+ * Should be serializable.
64
+ */
65
+ invoke(method, data) {
66
+ if (import.meta.hot) {
67
+ return new Promise((resolve, reject) => {
68
+ const handle = (response) => {
69
+ if (response.method !== method) {
70
+ return;
71
+ }
72
+ _a.response.unsubscribe(handle);
73
+ if (response.status === 'success') {
74
+ resolve(response.data);
75
+ }
76
+ else {
77
+ reject({
78
+ message: 'An error occurred while exporting the video.',
79
+ remarks: `Method: ${method}<br>Server error: ${response.message}`,
80
+ object: data,
81
+ });
82
+ }
83
+ };
84
+ _a.response.subscribe(handle);
85
+ import.meta.hot.send('revideo/ffmpeg', { method, data });
86
+ });
87
+ }
88
+ else {
89
+ throw new Error('FFmpegExporter can only be used locally.');
90
+ }
91
+ }
92
+ }
93
+ _a = FFmpegExporterClient;
94
+ FFmpegExporterClient.id = '@revideo/ffmpeg';
95
+ FFmpegExporterClient.displayName = 'Video (FFmpeg)';
96
+ FFmpegExporterClient.response = new EventDispatcher();
97
+ (() => {
98
+ if (import.meta.hot) {
99
+ import.meta.hot.on(`revideo/ffmpeg-ack`, (response) => _a.response.dispatch(response));
100
+ }
101
+ })();
102
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRkZtcGVnRXhwb3J0ZXJDbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9jbGllbnQvRkZtcGVnRXhwb3J0ZXJDbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQU9BLE9BQU8sRUFDTCxhQUFhLEVBQ2IsZUFBZSxFQUVmLGVBQWUsR0FFaEIsTUFBTSxlQUFlLENBQUM7QUFrQnZCOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sT0FBTyxvQkFBb0I7SUFJeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFnQjtRQUNqQyxPQUFPLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDM0MsU0FBUyxFQUFFLElBQUksYUFBYSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUM7WUFDaEQsWUFBWSxFQUFFLElBQUksYUFBYSxDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQzVELENBQUMsT0FBTyxDQUFDLEtBQUssQ0FDZjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFnQixFQUFFLFFBQTBCO1FBQ3JFLE9BQU8sSUFBSSxFQUFvQixDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBWUQsWUFDbUIsT0FBZ0IsRUFDaEIsUUFBMEI7UUFEMUIsWUFBTyxHQUFQLE9BQU8sQ0FBUztRQUNoQixhQUFRLEdBQVIsUUFBUSxDQUFrQjtJQUMxQyxDQUFDO0lBRUcsS0FBSyxDQUFDLEtBQUs7UUFDaEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBZ0MsQ0FBQztRQUN4RSxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1lBQ3pCLEdBQUcsSUFBSSxDQUFDLFFBQVE7WUFDaEIsR0FBRyxPQUFPO1lBQ1YsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLENB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
@@ -0,0 +1,3 @@
1
+ declare const _default: () => import("@revideo/core").Plugin;
2
+ export default _default;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../client/index.ts"],"names":[],"mappings":";AAIA,wBAKG"}
@@ -0,0 +1,9 @@
1
+ import { makePlugin } from '@revideo/core';
2
+ import { FFmpegExporterClient } from './FFmpegExporterClient';
3
+ export default makePlugin({
4
+ name: 'ffmpeg-plugin',
5
+ exporters() {
6
+ return [FFmpegExporterClient];
7
+ },
8
+ });
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9jbGllbnQvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUU1RCxlQUFlLFVBQVUsQ0FBQztJQUN4QixJQUFJLEVBQUUsZUFBZTtJQUNyQixTQUFTO1FBQ1AsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFDaEMsQ0FBQztDQUNGLENBQUMsQ0FBQyJ9
@@ -0,0 +1,19 @@
1
+ import { PluginConfig } from '@revideo/vite-plugin/lib/plugins';
2
+ import type { WebSocketServer } from 'vite';
3
+ /**
4
+ * A simple bridge between the FFmpegExporterServer and FFmpegExporterClient.
5
+ *
6
+ * @remarks
7
+ * This class lets the client exporter invoke methods on the server and receive
8
+ * responses using a simple Promise-based API.
9
+ */
10
+ export declare class FFmpegBridge {
11
+ private readonly ws;
12
+ private readonly config;
13
+ private process;
14
+ constructor(ws: WebSocketServer, config: PluginConfig);
15
+ private handleMessage;
16
+ private respondSuccess;
17
+ private respondError;
18
+ }
19
+ //# sourceMappingURL=FFmpegBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FFmpegBridge.d.ts","sourceRoot":"","sources":["../../server/FFmpegBridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,kCAAkC,CAAC;AAC9D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,MAAM,CAAC;AAW1C;;;;;;GAMG;AACH,qBAAa,YAAY;IAIrB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,OAAO,CAAqC;gBAGjC,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,YAAY;IAKvC,OAAO,CAAC,aAAa,CAkCnB;IAEF,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,YAAY;CAOrB"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FFmpegBridge = void 0;
4
+ const FFmpegExporterServer_1 = require("./FFmpegExporterServer");
5
+ /**
6
+ * A simple bridge between the FFmpegExporterServer and FFmpegExporterClient.
7
+ *
8
+ * @remarks
9
+ * This class lets the client exporter invoke methods on the server and receive
10
+ * responses using a simple Promise-based API.
11
+ */
12
+ class FFmpegBridge {
13
+ constructor(ws, config) {
14
+ this.ws = ws;
15
+ this.config = config;
16
+ this.process = null;
17
+ this.handleMessage = async ({ method, data }) => {
18
+ if (method === 'start') {
19
+ try {
20
+ this.process = new FFmpegExporterServer_1.FFmpegExporterServer(data, this.config);
21
+ this.respondSuccess(method, await this.process.start());
22
+ }
23
+ catch (e) {
24
+ this.respondError(method, e?.message);
25
+ }
26
+ return;
27
+ }
28
+ if (!this.process) {
29
+ this.respondError(method, 'The exporting process has not been started.');
30
+ return;
31
+ }
32
+ if (!(method in this.process)) {
33
+ this.respondError(method, `Unknown method: "${method}".`);
34
+ return;
35
+ }
36
+ try {
37
+ this.respondSuccess(method, await this.process[method](data));
38
+ }
39
+ catch (e) {
40
+ this.respondError(method, e?.message);
41
+ }
42
+ if (method === 'kill') {
43
+ this.process = null;
44
+ return;
45
+ }
46
+ };
47
+ ws.on('revideo/ffmpeg', this.handleMessage);
48
+ }
49
+ respondSuccess(method, data = {}) {
50
+ this.ws.send('revideo/ffmpeg-ack', {
51
+ status: 'success',
52
+ method,
53
+ data,
54
+ });
55
+ }
56
+ respondError(method, message = 'Unknown error.') {
57
+ this.ws.send('revideo/ffmpeg-ack', {
58
+ status: 'error',
59
+ method,
60
+ message,
61
+ });
62
+ }
63
+ }
64
+ exports.FFmpegBridge = FFmpegBridge;
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRkZtcGVnQnJpZGdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc2VydmVyL0ZGbXBlZ0JyaWRnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxpRUFHZ0M7QUFPaEM7Ozs7OztHQU1HO0FBQ0gsTUFBYSxZQUFZO0lBR3ZCLFlBQ21CLEVBQW1CLEVBQ25CLE1BQW9CO1FBRHBCLE9BQUUsR0FBRixFQUFFLENBQWlCO1FBQ25CLFdBQU0sR0FBTixNQUFNLENBQWM7UUFKL0IsWUFBTyxHQUFnQyxJQUFJLENBQUM7UUFTNUMsa0JBQWEsR0FBRyxLQUFLLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFpQixFQUFFLEVBQUU7WUFDL0QsSUFBSSxNQUFNLEtBQUssT0FBTyxFQUFFLENBQUM7Z0JBQ3ZCLElBQUksQ0FBQztvQkFDSCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksMkNBQW9CLENBQ3JDLElBQThCLEVBQzlCLElBQUksQ0FBQyxNQUFNLENBQ1osQ0FBQztvQkFDRixJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztnQkFDMUQsQ0FBQztnQkFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO29CQUNoQixJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQ3hDLENBQUM7Z0JBQ0QsT0FBTztZQUNULENBQUM7WUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNsQixJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSw2Q0FBNkMsQ0FBQyxDQUFDO2dCQUN6RSxPQUFPO1lBQ1QsQ0FBQztZQUVELElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDOUIsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsb0JBQW9CLE1BQU0sSUFBSSxDQUFDLENBQUM7Z0JBQzFELE9BQU87WUFDVCxDQUFDO1lBRUQsSUFBSSxDQUFDO2dCQUNILElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLE1BQU8sSUFBSSxDQUFDLE9BQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3pFLENBQUM7WUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO2dCQUNoQixJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDeEMsQ0FBQztZQUVELElBQUksTUFBTSxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUN0QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztnQkFDcEIsT0FBTztZQUNULENBQUM7UUFDSCxDQUFDLENBQUM7UUFyQ0EsRUFBRSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQXNDTyxjQUFjLENBQUMsTUFBYyxFQUFFLE9BQVksRUFBRTtRQUNuRCxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRTtZQUNqQyxNQUFNLEVBQUUsU0FBUztZQUNqQixNQUFNO1lBQ04sSUFBSTtTQUNMLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxZQUFZLENBQUMsTUFBYyxFQUFFLE9BQU8sR0FBRyxnQkFBZ0I7UUFDN0QsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUU7WUFDakMsTUFBTSxFQUFFLE9BQU87WUFDZixNQUFNO1lBQ04sT0FBTztTQUNSLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQTdERCxvQ0E2REMifQ==
@@ -0,0 +1,34 @@
1
+ import type { AssetInfo, RendererResult, RendererSettings } from '@revideo/core/lib/app';
2
+ import type { PluginConfig } from '@revideo/vite-plugin/lib/plugins';
3
+ export interface FFmpegExporterSettings extends RendererSettings {
4
+ audio?: string;
5
+ audioOffset?: number;
6
+ fastStart: boolean;
7
+ includeAudio: boolean;
8
+ }
9
+ /**
10
+ * The server-side implementation of the FFmpeg video exporter.
11
+ */
12
+ export declare class FFmpegExporterServer {
13
+ private readonly config;
14
+ private readonly stream;
15
+ private readonly command;
16
+ private readonly promise;
17
+ private readonly settings;
18
+ private readonly jobFolder;
19
+ constructor(settings: FFmpegExporterSettings, config: PluginConfig);
20
+ start(): Promise<void>;
21
+ handleFrame({ data }: {
22
+ data: string;
23
+ }): Promise<void>;
24
+ generateAudio({ assets, endFrame, }: {
25
+ assets: AssetInfo[][];
26
+ endFrame: number;
27
+ }): Promise<void>;
28
+ end(result: RendererResult): Promise<void>;
29
+ kill(): Promise<void>;
30
+ private prepareAudio;
31
+ private mergeAudioTracks;
32
+ private mergeAudioWithVideo;
33
+ }
34
+ //# sourceMappingURL=FFmpegExporterServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FFmpegExporterServer.d.ts","sourceRoot":"","sources":["../../server/FFmpegExporterServer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,kCAAkC,CAAC;AAcnE,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;CACvB;AAaD;;GAEG;AACH,qBAAa,oBAAoB;IAS7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IARzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGjC,QAAQ,EAAE,sBAAsB,EACf,MAAM,EAAE,YAAY;IAwC1B,KAAK;IAUL,WAAW,CAAC,EAAC,IAAI,EAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC;IAKlC,aAAa,CAAC,EACzB,MAAM,EACN,QAAQ,GACT,EAAE;QACD,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;KAClB;IAiCY,GAAG,CAAC,MAAM,EAAE,cAAc;IAc1B,IAAI;YAUH,YAAY;YAoDZ,gBAAgB;YAwBhB,mBAAmB;CAgClC"}
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FFmpegExporterServer = void 0;
4
+ const ffmpeg_1 = require("@ffmpeg-installer/ffmpeg");
5
+ const ffprobe_1 = require("@ffprobe-installer/ffprobe");
6
+ const ffmpeg = require("fluent-ffmpeg");
7
+ const fs = require("fs");
8
+ const os = require("os");
9
+ const path = require("path");
10
+ const uuid_1 = require("uuid");
11
+ const ImageStream_1 = require("./ImageStream");
12
+ const SAMPLE_RATE = 48000;
13
+ ffmpeg.setFfmpegPath(ffmpeg_1.path);
14
+ ffmpeg.setFfprobePath(ffprobe_1.path);
15
+ /**
16
+ * The server-side implementation of the FFmpeg video exporter.
17
+ */
18
+ class FFmpegExporterServer {
19
+ constructor(settings, config) {
20
+ this.config = config;
21
+ this.settings = settings;
22
+ this.jobFolder = path.join(os.tmpdir(), `revideo-${(0, uuid_1.v4)()}`);
23
+ this.stream = new ImageStream_1.ImageStream();
24
+ this.command = ffmpeg();
25
+ // Input image sequence
26
+ this.command
27
+ .input(this.stream)
28
+ .inputFormat('image2pipe')
29
+ .inputFps(settings.fps);
30
+ // Input audio file
31
+ if (settings.includeAudio && settings.audio) {
32
+ this.command
33
+ .input(settings.audio.slice(1))
34
+ // FIXME Offset only works for negative values.
35
+ .inputOptions([`-itsoffset ${settings.audioOffset ?? 0}`]);
36
+ }
37
+ // Output settings
38
+ const size = {
39
+ x: Math.round(settings.size.x * settings.resolutionScale),
40
+ y: Math.round(settings.size.y * settings.resolutionScale),
41
+ };
42
+ this.command
43
+ .output(path.join(this.jobFolder, `visuals.mp4`))
44
+ .outputOptions(['-pix_fmt yuv420p', '-shortest'])
45
+ .outputFps(settings.fps)
46
+ .size(`${size.x}x${size.y}`);
47
+ if (settings.fastStart) {
48
+ this.command.outputOptions(['-movflags +faststart']);
49
+ }
50
+ this.promise = new Promise((resolve, reject) => {
51
+ this.command.on('end', resolve).on('error', reject);
52
+ });
53
+ }
54
+ async start() {
55
+ if (!fs.existsSync(this.config.output)) {
56
+ await fs.promises.mkdir(this.config.output, { recursive: true });
57
+ }
58
+ if (!fs.existsSync(this.jobFolder)) {
59
+ await fs.promises.mkdir(this.jobFolder, { recursive: true });
60
+ }
61
+ this.command.run();
62
+ }
63
+ async handleFrame({ data }) {
64
+ const base64Data = data.slice(data.indexOf(',') + 1);
65
+ this.stream.pushImage(Buffer.from(base64Data, 'base64'));
66
+ }
67
+ async generateAudio({ assets, endFrame, }) {
68
+ const assetPositions = getAssetPlacement(assets);
69
+ const audioFilenames = [];
70
+ for (const asset of assetPositions) {
71
+ if (asset.type === 'video') {
72
+ const filename = await this.prepareAudio(asset, endFrame);
73
+ audioFilenames.push(filename);
74
+ }
75
+ else if (asset.type === 'audio') {
76
+ const filename = await this.prepareAudio(asset, endFrame);
77
+ audioFilenames.push(filename);
78
+ }
79
+ }
80
+ if (audioFilenames.length > 0) {
81
+ await this.mergeAudioTracks(audioFilenames);
82
+ await this.mergeAudioWithVideo(path.join(this.jobFolder, `audio.wav`), path.join(this.jobFolder, `visuals.mp4`));
83
+ }
84
+ else {
85
+ const destination = path.join(this.config.output, `${this.settings.name}.mp4`);
86
+ await fs.promises.copyFile(path.join(this.jobFolder, `visuals.mp4`), destination);
87
+ console.log(`Rendered successfully! Video saved to: ${destination}`);
88
+ }
89
+ }
90
+ async end(result) {
91
+ this.stream.pushImage(null);
92
+ if (result === 1) {
93
+ try {
94
+ this.command.kill('SIGKILL');
95
+ await this.promise;
96
+ }
97
+ catch (_) {
98
+ // do nothing
99
+ }
100
+ }
101
+ else {
102
+ await this.promise;
103
+ }
104
+ }
105
+ async kill() {
106
+ try {
107
+ await fs.promises.rm(this.jobFolder, { recursive: true, force: true }); // cleanup
108
+ this.command.kill('SIGKILL');
109
+ await this.promise;
110
+ }
111
+ catch (_) {
112
+ return;
113
+ }
114
+ }
115
+ async prepareAudio(asset, endFrame) {
116
+ // Construct the output path
117
+ const sanitizedKey = asset.key.replace(/[/[\]]/g, '-');
118
+ const outputPath = path.join(this.jobFolder, `${sanitizedKey}.wav`);
119
+ const trimRight = Math.min(asset.trimLeftInSeconds + asset.duration / this.settings.fps, asset.trimLeftInSeconds + endFrame / this.settings.fps);
120
+ const padStart = (asset.startInVideo / this.settings.fps) * 1000;
121
+ const padEnd = Math.max(0, (SAMPLE_RATE * endFrame) / this.settings.fps -
122
+ (SAMPLE_RATE * asset.duration) / this.settings.fps -
123
+ (SAMPLE_RATE * padStart) / 1000);
124
+ let resolvedPath;
125
+ if (asset.src.startsWith('/@fs')) {
126
+ resolvedPath = asset.src.replace('/@fs', '');
127
+ }
128
+ else {
129
+ resolvedPath = path.join(this.config.output, '..', asset.src);
130
+ }
131
+ await new Promise((resolve, reject) => {
132
+ ffmpeg(resolvedPath)
133
+ .audioChannels(2)
134
+ .audioCodec('pcm_s16le')
135
+ .audioFrequency(SAMPLE_RATE)
136
+ .outputOptions([
137
+ `-af`,
138
+ `atrim=start=${asset.trimLeftInSeconds}:end=${trimRight},apad=pad_len=${padEnd},adelay=${padStart}|${padStart}|${padStart}`,
139
+ ])
140
+ .on('end', () => {
141
+ resolve();
142
+ })
143
+ .on('error', err => {
144
+ console.error(`Error processing audio for asset key: ${asset.key}`, err);
145
+ reject(err);
146
+ })
147
+ .save(outputPath);
148
+ });
149
+ return outputPath;
150
+ }
151
+ async mergeAudioTracks(audioFilenames) {
152
+ return new Promise((resolve, reject) => {
153
+ const command = ffmpeg();
154
+ audioFilenames.forEach(filename => {
155
+ command.input(filename);
156
+ });
157
+ command
158
+ .complexFilter([
159
+ `amix=inputs=${audioFilenames.length}:duration=longest`,
160
+ ])
161
+ .outputOptions(['-c:a', 'pcm_s16le'])
162
+ .on('end', () => {
163
+ resolve();
164
+ })
165
+ .on('error', err => {
166
+ console.error(`Error merging audio tracks: ${err.message}`);
167
+ reject(err);
168
+ })
169
+ .save(path.join(this.jobFolder, `audio.wav`));
170
+ });
171
+ }
172
+ async mergeAudioWithVideo(audioPath, videoPath) {
173
+ return new Promise((resolve, reject) => {
174
+ ffmpeg()
175
+ .input(videoPath)
176
+ .input(audioPath)
177
+ .outputOptions([
178
+ '-c:v',
179
+ 'copy',
180
+ '-c:a',
181
+ 'aac',
182
+ '-strict',
183
+ 'experimental',
184
+ ])
185
+ .on('end', () => {
186
+ resolve();
187
+ console.log(`Rendered successfully! Video saved to: ${path.join(this.config.output, `${this.settings.name}.mp4`)}`);
188
+ })
189
+ .on('error', err => {
190
+ console.error(`Error merging video and audio: ${err.message}`);
191
+ reject(err);
192
+ })
193
+ .save(path.join(this.config.output, `${this.settings.name}.mp4`));
194
+ });
195
+ }
196
+ }
197
+ exports.FFmpegExporterServer = FFmpegExporterServer;
198
+ function getAssetPlacement(frames) {
199
+ const assets = [];
200
+ // A map to keep track of when each asset starts.
201
+ const assetStartMap = new Map();
202
+ for (let frame = 0; frame < frames.length; frame++) {
203
+ for (const asset of frames[frame]) {
204
+ if (!assetStartMap.has(asset.key)) {
205
+ assetStartMap.set(asset.key, frame);
206
+ assets.push({
207
+ key: asset.key,
208
+ src: asset.src,
209
+ type: asset.type,
210
+ startInVideo: frame,
211
+ endInVideo: frame,
212
+ duration: asset.duration,
213
+ playbackRate: asset.playbackRate,
214
+ trimLeftInSeconds: asset.currentTime,
215
+ });
216
+ }
217
+ else {
218
+ const existingAsset = assets.find(a => a.key === asset.key);
219
+ if (existingAsset) {
220
+ existingAsset.endInVideo = frame;
221
+ }
222
+ }
223
+ }
224
+ }
225
+ assets.forEach(asset => {
226
+ asset.duration = asset.endInVideo - asset.startInVideo + 1;
227
+ });
228
+ return assets;
229
+ }
230
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRkZtcGVnRXhwb3J0ZXJTZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zZXJ2ZXIvRkZtcGVnRXhwb3J0ZXJTZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQTREO0FBQzVELHdEQUErRDtBQVEvRCx3Q0FBd0M7QUFDeEMseUJBQXlCO0FBQ3pCLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFDN0IsK0JBQWtDO0FBQ2xDLCtDQUEwQztBQUUxQyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUM7QUFFMUIsTUFBTSxDQUFDLGFBQWEsQ0FBQyxhQUFVLENBQUMsQ0FBQztBQUNqQyxNQUFNLENBQUMsY0FBYyxDQUFDLGNBQVcsQ0FBQyxDQUFDO0FBb0JuQzs7R0FFRztBQUNILE1BQWEsb0JBQW9CO0lBTy9CLFlBQ0UsUUFBZ0MsRUFDZixNQUFvQjtRQUFwQixXQUFNLEdBQU4sTUFBTSxDQUFjO1FBRXJDLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsV0FBVyxJQUFBLFNBQU0sR0FBRSxFQUFFLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUkseUJBQVcsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxFQUFFLENBQUM7UUFFeEIsdUJBQXVCO1FBQ3ZCLElBQUksQ0FBQyxPQUFPO2FBQ1QsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7YUFDbEIsV0FBVyxDQUFDLFlBQVksQ0FBQzthQUN6QixRQUFRLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRTFCLG1CQUFtQjtRQUNuQixJQUFJLFFBQVEsQ0FBQyxZQUFZLElBQUksUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzVDLElBQUksQ0FBQyxPQUFPO2lCQUNULEtBQUssQ0FBRSxRQUFRLENBQUMsS0FBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzNDLCtDQUErQztpQkFDOUMsWUFBWSxDQUFDLENBQUMsY0FBYyxRQUFRLENBQUMsV0FBVyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMvRCxDQUFDO1FBRUQsa0JBQWtCO1FBQ2xCLE1BQU0sSUFBSSxHQUFHO1lBQ1gsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLGVBQWUsQ0FBQztZQUN6RCxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsZUFBZSxDQUFDO1NBQzFELENBQUM7UUFDRixJQUFJLENBQUMsT0FBTzthQUNULE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsYUFBYSxDQUFDLENBQUM7YUFDaEQsYUFBYSxDQUFDLENBQUMsa0JBQWtCLEVBQUUsV0FBVyxDQUFDLENBQUM7YUFDaEQsU0FBUyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUM7YUFDdkIsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvQixJQUFJLFFBQVEsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQztRQUN2RCxDQUFDO1FBRUQsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNuRCxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUN0RCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsS0FBSztRQUNoQixJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDdkMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFDRCxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUNuQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBQyxTQUFTLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRU0sS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFDLElBQUksRUFBaUI7UUFDN0MsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVNLEtBQUssQ0FBQyxhQUFhLENBQUMsRUFDekIsTUFBTSxFQUNOLFFBQVEsR0FJVDtRQUNDLE1BQU0sY0FBYyxHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRWpELE1BQU0sY0FBYyxHQUFhLEVBQUUsQ0FBQztRQUNwQyxLQUFLLE1BQU0sS0FBSyxJQUFJLGNBQWMsRUFBRSxDQUFDO1lBQ25DLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztnQkFDM0IsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztnQkFDMUQsY0FBYyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNoQyxDQUFDO2lCQUFNLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztnQkFDbEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztnQkFDMUQsY0FBYyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNoQyxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksY0FBYyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM5QixNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1QyxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FDNUIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFdBQVcsQ0FBQyxFQUN0QyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsYUFBYSxDQUFDLENBQ3pDLENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQzNCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUNsQixHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxNQUFNLENBQzVCLENBQUM7WUFDRixNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsYUFBYSxDQUFDLEVBQ3hDLFdBQVcsQ0FDWixDQUFDO1lBQ0YsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUN2RSxDQUFDO0lBQ0gsQ0FBQztJQUVNLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBc0I7UUFDckMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUIsSUFBSSxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDO2dCQUNILElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUM3QixNQUFNLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDckIsQ0FBQztZQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ1gsYUFBYTtZQUNmLENBQUM7UUFDSCxDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUNyQixDQUFDO0lBQ0gsQ0FBQztJQUVNLEtBQUssQ0FBQyxJQUFJO1FBQ2YsSUFBSSxDQUFDO1lBQ0gsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEVBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVU7WUFDaEYsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDN0IsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQ3JCLENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1gsT0FBTztRQUNULENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLFlBQVksQ0FDeEIsS0FBaUIsRUFDakIsUUFBZ0I7UUFFaEIsNEJBQTRCO1FBQzVCLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUN2RCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsR0FBRyxZQUFZLE1BQU0sQ0FBQyxDQUFDO1FBRXBFLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQ3hCLEtBQUssQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUM1RCxLQUFLLENBQUMsaUJBQWlCLEdBQUcsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUN2RCxDQUFDO1FBQ0YsTUFBTSxRQUFRLEdBQUcsQ0FBQyxLQUFLLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBQ2pFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQ3JCLENBQUMsRUFDRCxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUc7WUFDMUMsQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRztZQUNsRCxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUMsR0FBRyxJQUFJLENBQ2xDLENBQUM7UUFFRixJQUFJLFlBQW9CLENBQUM7UUFDekIsSUFBSSxLQUFLLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ2pDLFlBQVksR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDL0MsQ0FBQzthQUFNLENBQUM7WUFDTixZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2hFLENBQUM7UUFFRCxNQUFNLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzFDLE1BQU0sQ0FBQyxZQUFZLENBQUM7aUJBQ2pCLGFBQWEsQ0FBQyxDQUFDLENBQUM7aUJBQ2hCLFVBQVUsQ0FBQyxXQUFXLENBQUM7aUJBQ3ZCLGNBQWMsQ0FBQyxXQUFXLENBQUM7aUJBQzNCLGFBQWEsQ0FBQztnQkFDYixLQUFLO2dCQUNMLGVBQWUsS0FBSyxDQUFDLGlCQUFpQixRQUFRLFNBQVMsaUJBQWlCLE1BQU0sV0FBVyxRQUFRLElBQUksUUFBUSxJQUFJLFFBQVEsRUFBRTthQUM1SCxDQUFDO2lCQUNELEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFO2dCQUNkLE9BQU8sRUFBRSxDQUFDO1lBQ1osQ0FBQyxDQUFDO2lCQUNELEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLEVBQUU7Z0JBQ2pCLE9BQU8sQ0FBQyxLQUFLLENBQ1gseUNBQXlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFDcEQsR0FBRyxDQUNKLENBQUM7Z0JBQ0YsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2QsQ0FBQyxDQUFDO2lCQUNELElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN0QixDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFTyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsY0FBd0I7UUFDckQsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxNQUFNLE9BQU8sR0FBRyxNQUFNLEVBQUUsQ0FBQztZQUV6QixjQUFjLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFO2dCQUNoQyxPQUFPLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzFCLENBQUMsQ0FBQyxDQUFDO1lBRUgsT0FBTztpQkFDSixhQUFhLENBQUM7Z0JBQ2IsZUFBZSxjQUFjLENBQUMsTUFBTSxtQkFBbUI7YUFDeEQsQ0FBQztpQkFDRCxhQUFhLENBQUMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7aUJBQ3BDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFO2dCQUNkLE9BQU8sRUFBRSxDQUFDO1lBQ1osQ0FBQyxDQUFDO2lCQUNELEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLEVBQUU7Z0JBQ2pCLE9BQU8sQ0FBQyxLQUFLLENBQUMsK0JBQStCLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUM1RCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDZCxDQUFDLENBQUM7aUJBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ2xELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxtQkFBbUIsQ0FDL0IsU0FBaUIsRUFDakIsU0FBaUI7UUFFakIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxNQUFNLEVBQUU7aUJBQ0wsS0FBSyxDQUFDLFNBQVMsQ0FBQztpQkFDaEIsS0FBSyxDQUFDLFNBQVMsQ0FBQztpQkFDaEIsYUFBYSxDQUFDO2dCQUNiLE1BQU07Z0JBQ04sTUFBTTtnQkFDTixNQUFNO2dCQUNOLEtBQUs7Z0JBQ0wsU0FBUztnQkFDVCxjQUFjO2FBQ2YsQ0FBQztpQkFDRCxFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRTtnQkFDZCxPQUFPLEVBQUUsQ0FBQztnQkFDVixPQUFPLENBQUMsR0FBRyxDQUNULDBDQUEwQyxJQUFJLENBQUMsSUFBSSxDQUNqRCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFDbEIsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksTUFBTSxDQUM1QixFQUFFLENBQ0osQ0FBQztZQUNKLENBQUMsQ0FBQztpQkFDRCxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxFQUFFO2dCQUNqQixPQUFPLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztnQkFDL0QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2QsQ0FBQyxDQUFDO2lCQUNELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDdEUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUEzT0Qsb0RBMk9DO0FBRUQsU0FBUyxpQkFBaUIsQ0FBQyxNQUFxQjtJQUM5QyxNQUFNLE1BQU0sR0FBaUIsRUFBRSxDQUFDO0lBRWhDLGlEQUFpRDtJQUNqRCxNQUFNLGFBQWEsR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztJQUVoRCxLQUFLLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ25ELEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ2xDLGFBQWEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDcEMsTUFBTSxDQUFDLElBQUksQ0FBQztvQkFDVixHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUc7b0JBQ2QsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHO29CQUNkLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtvQkFDaEIsWUFBWSxFQUFFLEtBQUs7b0JBQ25CLFVBQVUsRUFBRSxLQUFLO29CQUNqQixRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVE7b0JBQ3hCLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWTtvQkFDaEMsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLFdBQVc7aUJBQ3JDLENBQUMsQ0FBQztZQUNMLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzVELElBQUksYUFBYSxFQUFFLENBQUM7b0JBQ2xCLGFBQWEsQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO2dCQUNuQyxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtRQUNyQixLQUFLLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUM7SUFDN0QsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIn0=
@@ -0,0 +1,10 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { Readable } from 'stream';
4
+ export declare class ImageStream extends Readable {
5
+ private image;
6
+ private hasData;
7
+ pushImage(image: Buffer | null): void;
8
+ _read(): void;
9
+ }
10
+ //# sourceMappingURL=ImageStream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageStream.d.ts","sourceRoot":"","sources":["../../server/ImageStream.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,QAAQ,CAAC;AAEhC,qBAAa,WAAY,SAAQ,QAAQ;IACvC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,OAAO,CAAS;IAEjB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOrB,KAAK;CAMtB"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImageStream = void 0;
4
+ const stream_1 = require("stream");
5
+ class ImageStream extends stream_1.Readable {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.image = null;
9
+ this.hasData = false;
10
+ }
11
+ pushImage(image) {
12
+ this.image = image;
13
+ this.hasData = true;
14
+ this._read();
15
+ }
16
+ // eslint-disable-next-line @typescript-eslint/naming-convention
17
+ _read() {
18
+ if (this.hasData) {
19
+ this.hasData = false;
20
+ this.push(this.image);
21
+ }
22
+ }
23
+ }
24
+ exports.ImageStream = ImageStream;
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSW1hZ2VTdHJlYW0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zZXJ2ZXIvSW1hZ2VTdHJlYW0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQWdDO0FBRWhDLE1BQWEsV0FBWSxTQUFRLGlCQUFRO0lBQXpDOztRQUNVLFVBQUssR0FBa0IsSUFBSSxDQUFDO1FBQzVCLFlBQU8sR0FBRyxLQUFLLENBQUM7SUFlMUIsQ0FBQztJQWJRLFNBQVMsQ0FBQyxLQUFvQjtRQUNuQyxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNwQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDZixDQUFDO0lBRUQsZ0VBQWdFO0lBQ2hELEtBQUs7UUFDbkIsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7WUFDckIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEIsQ0FBQztJQUNILENBQUM7Q0FDRjtBQWpCRCxrQ0FpQkMifQ==
@@ -0,0 +1,4 @@
1
+ import { Plugin } from '@revideo/vite-plugin/lib/plugins';
2
+ declare const _default: () => Plugin;
3
+ export default _default;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAGP,MAAM,kCAAkC,CAAC;8BAGvB,MAAM;AAAzB,wBAcE"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const plugins_1 = require("@revideo/vite-plugin/lib/plugins");
4
+ const FFmpegBridge_1 = require("./FFmpegBridge");
5
+ exports.default = () => {
6
+ let config;
7
+ return {
8
+ name: 'revideo/ffmpeg',
9
+ [plugins_1.PLUGIN_OPTIONS]: {
10
+ entryPoint: '@revideo/ffmpeg/lib/client',
11
+ async config(value) {
12
+ config = value;
13
+ },
14
+ },
15
+ configureServer(server) {
16
+ new FFmpegBridge_1.FFmpegBridge(server.ws, config);
17
+ },
18
+ };
19
+ };
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zZXJ2ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw4REFJMEM7QUFDMUMsaURBQTRDO0FBRTVDLGtCQUFlLEdBQVcsRUFBRTtJQUMxQixJQUFJLE1BQW9CLENBQUM7SUFDekIsT0FBTztRQUNMLElBQUksRUFBRSxnQkFBZ0I7UUFDdEIsQ0FBQyx3QkFBYyxDQUFDLEVBQUU7WUFDaEIsVUFBVSxFQUFFLDRCQUE0QjtZQUN4QyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUs7Z0JBQ2hCLE1BQU0sR0FBRyxLQUFLLENBQUM7WUFDakIsQ0FBQztTQUNGO1FBQ0QsZUFBZSxDQUFDLE1BQU07WUFDcEIsSUFBSSwyQkFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDdEMsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDLENBQUMifQ==
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@revideo/ffmpeg",
3
+ "version": "0.1.0",
4
+ "description": "An FFmpeg video exporter for revideo",
5
+ "main": "lib/server/index.js",
6
+ "author": "revideo",
7
+ "homepage": "https://re.video/",
8
+ "bugs": "https://github.com/havenhq/revideo/issues",
9
+ "license": "MIT",
10
+ "scripts": {
11
+ "build": "npm run client:build && npm run server:build",
12
+ "client:build": "tsc --project client/tsconfig.json",
13
+ "client:dev": "tsc -w --project client/tsconfig.json",
14
+ "server:build": "tsc --project server/tsconfig.json",
15
+ "server:dev": "tsc -w --project server/tsconfig.json"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/havenhq/revideo.git"
20
+ },
21
+ "files": [
22
+ "lib"
23
+ ],
24
+ "devDependencies": {
25
+ "@types/fluent-ffmpeg": "^2.1.21"
26
+ },
27
+ "dependencies": {
28
+ "@ffmpeg-installer/ffmpeg": "^1.1.0",
29
+ "@ffprobe-installer/ffprobe": "^2.0.0",
30
+ "@revideo/core": "^0.1.0",
31
+ "@revideo/vite-plugin": "^0.1.0",
32
+ "fluent-ffmpeg": "^2.1.2",
33
+ "vite": "^4.5"
34
+ },
35
+ "gitHead": "48bf2971cfa1dec7ea92ee0d418c35772f7ea84d"
36
+ }