@revideo/ffmpeg 0.2.13 → 0.2.14-alpha.933

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.
Files changed (35) hide show
  1. package/{lib/server/FFmpegExporterServer.d.ts → dist/ffmpeg-exporter-server.d.ts} +4 -20
  2. package/dist/ffmpeg-exporter-server.d.ts.map +1 -0
  3. package/dist/ffmpeg-exporter-server.js +249 -0
  4. package/{lib/server/ImageStream.d.ts → dist/image-stream.d.ts} +1 -1
  5. package/dist/image-stream.d.ts.map +1 -0
  6. package/dist/image-stream.js +25 -0
  7. package/dist/index.d.ts +4 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +20 -0
  10. package/dist/tsconfig.tsbuildinfo +1 -0
  11. package/dist/utils.d.ts +9 -0
  12. package/dist/utils.d.ts.map +1 -0
  13. package/dist/utils.js +161 -0
  14. package/{lib/server/VideoFrameExtractor.d.ts → dist/video-frame-extractor.d.ts} +6 -3
  15. package/dist/video-frame-extractor.d.ts.map +1 -0
  16. package/dist/video-frame-extractor.js +160 -0
  17. package/package.json +14 -25
  18. package/lib/client/FFmpegExporterClient.d.ts +0 -46
  19. package/lib/client/FFmpegExporterClient.d.ts.map +0 -1
  20. package/lib/client/FFmpegExporterClient.js +0 -118
  21. package/lib/client/index.d.ts +0 -3
  22. package/lib/client/index.d.ts.map +0 -1
  23. package/lib/client/index.js +0 -9
  24. package/lib/server/FFmpegBridge.d.ts +0 -22
  25. package/lib/server/FFmpegBridge.d.ts.map +0 -1
  26. package/lib/server/FFmpegBridge.js +0 -92
  27. package/lib/server/FFmpegExporterServer.d.ts.map +0 -1
  28. package/lib/server/FFmpegExporterServer.js +0 -317
  29. package/lib/server/ImageStream.d.ts.map +0 -1
  30. package/lib/server/ImageStream.js +0 -25
  31. package/lib/server/VideoFrameExtractor.d.ts.map +0 -1
  32. package/lib/server/VideoFrameExtractor.js +0 -148
  33. package/lib/server/index.d.ts +0 -4
  34. package/lib/server/index.d.ts.map +0 -1
  35. package/lib/server/index.js +0 -20
@@ -1,92 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FFmpegBridge = void 0;
4
- const FFmpegExporterServer_1 = require("./FFmpegExporterServer");
5
- const VideoFrameExtractor_1 = require("./VideoFrameExtractor");
6
- /**
7
- * A simple bridge between the FFmpegExporterServer and FFmpegExporterClient.
8
- *
9
- * @remarks
10
- * This class lets the client exporter invoke methods on the server and receive
11
- * responses using a simple Promise-based API.
12
- */
13
- class FFmpegBridge {
14
- constructor(ws, config) {
15
- this.ws = ws;
16
- this.config = config;
17
- this.process = null;
18
- this.handleMessage = async ({ method, data }) => {
19
- if (method === 'start') {
20
- try {
21
- this.process = new FFmpegExporterServer_1.FFmpegExporterServer(data, this.config);
22
- this.respondSuccess(method, await this.process.start());
23
- }
24
- catch (e) {
25
- this.respondError(method, e?.message);
26
- }
27
- return;
28
- }
29
- if (!this.process) {
30
- this.respondError(method, 'The exporting process has not been started.');
31
- return;
32
- }
33
- if (!(method in this.process)) {
34
- this.respondError(method, `Unknown method: "${method}".`);
35
- return;
36
- }
37
- try {
38
- this.respondSuccess(method, await this.process[method](data));
39
- }
40
- catch (e) {
41
- this.respondError(method, e?.message);
42
- }
43
- if (method === 'kill') {
44
- this.process = null;
45
- return;
46
- }
47
- };
48
- // List of VideoFrameExtractors
49
- this.videoFrameExtractors = new Map();
50
- this.handleVideoFrameMessage = async ({ data }) => {
51
- const typedData = data;
52
- // Check if we already have a VideoFrameExtractor for this video
53
- const id = typedData.filePath + '-' + typedData.id;
54
- let extractor = this.videoFrameExtractors.get(id);
55
- if (!extractor) {
56
- extractor = new VideoFrameExtractor_1.VideoFrameExtractor(typedData.filePath, typedData.startTime, typedData.fps, typedData.duration);
57
- this.videoFrameExtractors.set(id, extractor);
58
- }
59
- // Go to the frame that is closest to the requested time
60
- const frame = await extractor.popImage();
61
- this.ws.send('revideo:ffmpeg-video-frame-res', {
62
- status: 'success',
63
- data: {
64
- frame,
65
- },
66
- });
67
- };
68
- this.handleRenderFinished = async () => {
69
- this.videoFrameExtractors.forEach(extractor => extractor.destroy());
70
- this.videoFrameExtractors.clear();
71
- };
72
- ws.on('revideo:ffmpeg-exporter', this.handleMessage);
73
- ws.on('revideo:ffmpeg-video-frame', this.handleVideoFrameMessage);
74
- ws.on('revideo:render-finished', this.handleRenderFinished);
75
- }
76
- respondSuccess(method, data = {}) {
77
- this.ws.send('revideo:ffmpeg-exporter-ack', {
78
- status: 'success',
79
- method,
80
- data,
81
- });
82
- }
83
- respondError(method, message = 'Unknown error.') {
84
- this.ws.send('revideo:ffmpeg-exporter-ack', {
85
- status: 'error',
86
- method,
87
- message,
88
- });
89
- }
90
- }
91
- exports.FFmpegBridge = FFmpegBridge;
92
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRkZtcGVnQnJpZGdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc2VydmVyL0ZGbXBlZ0JyaWRnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxpRUFHZ0M7QUFDaEMsK0RBQTBEO0FBTzFEOzs7Ozs7R0FNRztBQUNILE1BQWEsWUFBWTtJQUd2QixZQUNtQixFQUFtQixFQUNuQixNQUFvQjtRQURwQixPQUFFLEdBQUYsRUFBRSxDQUFpQjtRQUNuQixXQUFNLEdBQU4sTUFBTSxDQUFjO1FBSi9CLFlBQU8sR0FBZ0MsSUFBSSxDQUFDO1FBVzVDLGtCQUFhLEdBQUcsS0FBSyxFQUFFLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBaUIsRUFBRSxFQUFFO1lBQy9ELElBQUksTUFBTSxLQUFLLE9BQU8sRUFBRSxDQUFDO2dCQUN2QixJQUFJLENBQUM7b0JBQ0gsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLDJDQUFvQixDQUNyQyxJQUE4QixFQUM5QixJQUFJLENBQUMsTUFBTSxDQUNaLENBQUM7b0JBQ0YsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7Z0JBQzFELENBQUM7Z0JBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztvQkFDaEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUN4QyxDQUFDO2dCQUNELE9BQU87WUFDVCxDQUFDO1lBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDbEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsNkNBQTZDLENBQUMsQ0FBQztnQkFDekUsT0FBTztZQUNULENBQUM7WUFFRCxJQUFJLENBQUMsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQzlCLElBQUksQ0FBQyxZQUFZLENB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
@@ -1 +0,0 @@
1
- {"version":3,"file":"FFmpegExporterServer.d.ts","sourceRoot":"","sources":["../../server/FFmpegExporterServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,kCAAkC,CAAC;AAanE,wBAAsB,iBAAiB,iBAatC;AAED,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;AAED,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,oBAAoB;IAU7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IATzB,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;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;gBAGxC,QAAQ,EAAE,sBAAsB,EACf,MAAM,EAAE,YAAY;IAyC1B,KAAK;IAYL,WAAW,CAAC,EAAC,IAAI,EAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC;IAKlC,aAAa,CAAC,EACzB,MAAM,EACN,UAAU,EACV,QAAQ,GACT,EAAE;QACD,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB;IAoBY,UAAU;IAmBvB,OAAO,CAAC,WAAW;IAcN,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAuBxD,GAAG,CAAC,MAAM,EAAE,cAAc;IAc1B,IAAI;YAUH,YAAY;YAyDZ,gBAAgB;YAwBhB,sBAAsB;YA4BtB,mBAAmB;CAgClC"}
@@ -1,317 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FFmpegExporterServer = exports.getCurrentVersion = void 0;
4
- const ffmpeg = require("fluent-ffmpeg");
5
- const fs = require("fs");
6
- const os = require("os");
7
- const path = require("path");
8
- const uuid_1 = require("uuid");
9
- const ImageStream_1 = require("./ImageStream");
10
- const telemetry_1 = require("@revideo/telemetry");
11
- const fsPromises = require("fs/promises");
12
- const SAMPLE_RATE = 48000;
13
- async function getCurrentVersion() {
14
- try {
15
- const packageData = JSON.parse(await fsPromises.readFile(path.join(__dirname, '..', '..', 'package.json'), 'utf-8'));
16
- return packageData.version;
17
- }
18
- catch (e) {
19
- return 'ERROR';
20
- }
21
- }
22
- exports.getCurrentVersion = getCurrentVersion;
23
- /**
24
- * The server-side implementation of the FFmpeg video exporter.
25
- */
26
- class FFmpegExporterServer {
27
- constructor(settings, config) {
28
- this.config = config;
29
- this.settings = settings;
30
- this.jobFolder = path.join(os.tmpdir(), `revideo-${(0, uuid_1.v4)()}`);
31
- this.audioFilenames = [];
32
- this.stream = new ImageStream_1.ImageStream();
33
- this.command = ffmpeg();
34
- // Input image sequence
35
- this.command
36
- .input(this.stream)
37
- .inputFormat('image2pipe')
38
- .inputFps(settings.fps);
39
- // Input audio file
40
- if (settings.includeAudio && settings.audio) {
41
- this.command
42
- .input(settings.audio.slice(1))
43
- // FIXME Offset only works for negative values.
44
- .inputOptions([`-itsoffset ${settings.audioOffset ?? 0}`]);
45
- }
46
- // Output settings
47
- const size = {
48
- x: Math.round(settings.size.x * settings.resolutionScale),
49
- y: Math.round(settings.size.y * settings.resolutionScale),
50
- };
51
- this.command
52
- .output(path.join(this.jobFolder, `visuals.mp4`))
53
- .outputOptions(['-pix_fmt yuv420p', '-shortest'])
54
- .outputFps(settings.fps)
55
- .size(`${size.x}x${size.y}`);
56
- if (settings.fastStart) {
57
- this.command.outputOptions(['-movflags +faststart']);
58
- }
59
- this.promise = new Promise((resolve, reject) => {
60
- this.command.on('end', resolve).on('error', reject);
61
- });
62
- }
63
- async start() {
64
- const version = await getCurrentVersion();
65
- (0, telemetry_1.sendEvent)(telemetry_1.EventName.RenderStarted, { version });
66
- if (!fs.existsSync(this.config.output)) {
67
- await fs.promises.mkdir(this.config.output, { recursive: true });
68
- }
69
- if (!fs.existsSync(this.jobFolder)) {
70
- await fs.promises.mkdir(this.jobFolder, { recursive: true });
71
- }
72
- this.command.run();
73
- }
74
- async handleFrame({ data }) {
75
- const base64Data = data.slice(data.indexOf(',') + 1);
76
- this.stream.pushImage(Buffer.from(base64Data, 'base64'));
77
- }
78
- async generateAudio({ assets, startFrame, endFrame, }) {
79
- const assetPositions = getAssetPlacement(assets);
80
- for (const asset of assetPositions) {
81
- let hasAudioStream = true;
82
- if (asset.type !== 'audio') {
83
- hasAudioStream = await this.checkForAudioStream(asset);
84
- }
85
- if (asset.playbackRate !== 0 && asset.volume !== 0 && hasAudioStream) {
86
- const filename = await this.prepareAudio(asset, startFrame, endFrame);
87
- this.audioFilenames.push(filename);
88
- }
89
- }
90
- if (this.audioFilenames.length > 0) {
91
- await this.mergeAudioTracks();
92
- }
93
- }
94
- async mergeMedia() {
95
- if (this.audioFilenames.length > 0) {
96
- await this.mergeAudioWithVideo(path.join(this.jobFolder, `audio.wav`), path.join(this.jobFolder, `visuals.mp4`));
97
- }
98
- else {
99
- const destination = path.join(this.config.output, `${this.settings.name}.mp4`);
100
- await fs.promises.copyFile(path.join(this.jobFolder, `visuals.mp4`), destination);
101
- console.log(`\nRendered successfully! Video saved to: ${destination}`);
102
- }
103
- }
104
- resolvePath(assetPath) {
105
- let resolvedPath;
106
- if (assetPath.startsWith('/@fs')) {
107
- resolvedPath = assetPath.replace('/@fs', '');
108
- }
109
- else if (assetPath.startsWith('http')) {
110
- resolvedPath = assetPath;
111
- }
112
- else if (assetPath.startsWith('/')) {
113
- resolvedPath = path.join(this.config.output, '../public', assetPath);
114
- }
115
- else {
116
- resolvedPath = path.join(this.config.output, '..', assetPath);
117
- }
118
- return resolvedPath;
119
- }
120
- async checkForAudioStream(asset) {
121
- const resolvedPath = this.resolvePath(asset.src);
122
- return new Promise((resolve, reject) => {
123
- ffmpeg.ffprobe(resolvedPath, (err, metadata) => {
124
- if (err) {
125
- console.error('error checking for audioStream for asset', asset.key, err);
126
- reject(err);
127
- return;
128
- }
129
- const audioStreams = metadata.streams.filter(s => s.codec_type === 'audio');
130
- resolve(audioStreams.length > 0);
131
- });
132
- });
133
- }
134
- async end(result) {
135
- this.stream.pushImage(null);
136
- if (result === 1) {
137
- try {
138
- this.command.kill('SIGKILL');
139
- await this.promise;
140
- }
141
- catch (_) {
142
- // do nothing
143
- }
144
- }
145
- else {
146
- await this.promise;
147
- }
148
- }
149
- async kill() {
150
- try {
151
- await fs.promises.rm(this.jobFolder, { recursive: true, force: true }); // cleanup
152
- this.command.kill('SIGKILL');
153
- await this.promise;
154
- }
155
- catch (_) {
156
- return;
157
- }
158
- }
159
- async prepareAudio(asset, startFrame, endFrame) {
160
- // Construct the output path
161
- const sanitizedKey = asset.key.replace(/[/[\]]/g, '-');
162
- const outputPath = path.join(this.jobFolder, `${sanitizedKey}.wav`);
163
- const trimLeft = asset.trimLeftInSeconds / asset.playbackRate;
164
- const trimRight = Math.min(trimLeft + asset.duration / this.settings.fps, trimLeft + (endFrame - startFrame + 1) / this.settings.fps);
165
- const padStart = (asset.startInVideo / this.settings.fps) * 1000;
166
- const assetSampleRate = await getSampleRate(this.resolvePath(asset.src));
167
- const padEnd = Math.max(0, (assetSampleRate * (endFrame - startFrame + 1)) / this.settings.fps -
168
- (assetSampleRate * asset.duration) / this.settings.fps -
169
- (assetSampleRate * padStart) / 1000);
170
- const atempoFilters = await this.calculateAtempoFilters(asset.playbackRate); // atempo filter value must be >=0.5 and <=100. If the value is higher or lower, this function sets multiple atempo filters
171
- const resolvedPath = this.resolvePath(asset.src);
172
- await new Promise((resolve, reject) => {
173
- const audioFilters = [
174
- ...atempoFilters,
175
- `atrim=start=${trimLeft}:end=${trimRight}`,
176
- `apad=pad_len=${padEnd}`,
177
- `adelay=${padStart}|${padStart}|${padStart}`,
178
- `volume=${asset.volume}`,
179
- ].join(',');
180
- ffmpeg(resolvedPath)
181
- .audioChannels(2)
182
- .audioCodec('pcm_s16le')
183
- .audioFrequency(SAMPLE_RATE)
184
- .outputOptions([`-af`, audioFilters])
185
- .on('end', () => {
186
- resolve();
187
- })
188
- .on('error', err => {
189
- console.error(`Error processing audio for asset key: ${asset.key}`, err);
190
- reject(err);
191
- })
192
- .save(outputPath);
193
- });
194
- return outputPath;
195
- }
196
- async mergeAudioTracks() {
197
- return new Promise((resolve, reject) => {
198
- const command = ffmpeg();
199
- this.audioFilenames.forEach(filename => {
200
- command.input(filename);
201
- });
202
- command
203
- .complexFilter([
204
- `amix=inputs=${this.audioFilenames.length}:duration=longest`,
205
- ])
206
- .outputOptions(['-c:a', 'pcm_s16le'])
207
- .on('end', () => {
208
- resolve();
209
- })
210
- .on('error', err => {
211
- console.error(`Error merging audio tracks: ${err.message}`);
212
- reject(err);
213
- })
214
- .save(path.join(this.jobFolder, `audio.wav`));
215
- });
216
- }
217
- async calculateAtempoFilters(playbackRate) {
218
- const atempoFilters = [];
219
- // Calculate how many times we need to 100x the speed
220
- let rate = playbackRate;
221
- while (rate > 100.0) {
222
- atempoFilters.push('atempo=100.0');
223
- rate /= 100.0;
224
- }
225
- // Add the last atempo filter with the remaining rate
226
- if (rate > 1.0) {
227
- atempoFilters.push(`atempo=${rate}`);
228
- }
229
- // Calculate how many times we need to halve the speed
230
- rate = playbackRate;
231
- while (rate < 0.5) {
232
- atempoFilters.push('atempo=0.5');
233
- rate *= 2.0;
234
- }
235
- // Add the last atempo filter with the remaining rate
236
- if (rate < 1.0) {
237
- atempoFilters.push(`atempo=${rate}`);
238
- }
239
- return atempoFilters;
240
- }
241
- async mergeAudioWithVideo(audioPath, videoPath) {
242
- return new Promise((resolve, reject) => {
243
- ffmpeg()
244
- .input(videoPath)
245
- .input(audioPath)
246
- .outputOptions([
247
- '-c:v',
248
- 'copy',
249
- '-c:a',
250
- 'aac',
251
- '-strict',
252
- 'experimental',
253
- ])
254
- .on('end', () => {
255
- resolve();
256
- console.log(`\nRendered successfully! Video saved to: ${path.join(this.config.output, `${this.settings.name}.mp4`)}`);
257
- })
258
- .on('error', err => {
259
- console.error(`Error merging video and audio: ${err.message}`);
260
- reject(err);
261
- })
262
- .save(path.join(this.config.output, `${this.settings.name}.mp4`));
263
- });
264
- }
265
- }
266
- exports.FFmpegExporterServer = FFmpegExporterServer;
267
- function getAssetPlacement(frames) {
268
- const assets = [];
269
- // A map to keep track of when each asset starts.
270
- const assetStartMap = new Map();
271
- for (let frame = 0; frame < frames.length; frame++) {
272
- for (const asset of frames[frame]) {
273
- if (!assetStartMap.has(asset.key)) {
274
- assetStartMap.set(asset.key, frame);
275
- assets.push({
276
- key: asset.key,
277
- src: asset.src,
278
- type: asset.type,
279
- startInVideo: frame,
280
- endInVideo: frame,
281
- duration: asset.duration,
282
- playbackRate: asset.playbackRate,
283
- volume: asset.volume,
284
- trimLeftInSeconds: asset.currentTime,
285
- });
286
- }
287
- else {
288
- const existingAsset = assets.find(a => a.key === asset.key);
289
- if (existingAsset) {
290
- existingAsset.endInVideo = frame;
291
- }
292
- }
293
- }
294
- }
295
- assets.forEach(asset => {
296
- asset.duration = asset.endInVideo - asset.startInVideo + 1;
297
- });
298
- return assets;
299
- }
300
- async function getSampleRate(filePath) {
301
- return new Promise((resolve, reject) => {
302
- ffmpeg.ffprobe(filePath, (err, metadata) => {
303
- if (err) {
304
- reject(err);
305
- return;
306
- }
307
- const audioStream = metadata.streams.find(s => s.codec_type === 'audio');
308
- if (audioStream && audioStream.sample_rate) {
309
- resolve(audioStream.sample_rate);
310
- }
311
- else {
312
- reject(new Error('No audio stream found'));
313
- }
314
- });
315
- });
316
- }
317
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRkZtcGVnRXhwb3J0ZXJTZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zZXJ2ZXIvRkZtcGVnRXhwb3J0ZXJTZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBT0Esd0NBQXdDO0FBQ3hDLHlCQUF5QjtBQUN6Qix5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLCtCQUFrQztBQUNsQywrQ0FBMEM7QUFFMUMsa0RBQXdEO0FBQ3hELDBDQUEwQztBQUMxQyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUM7QUFFbkIsS0FBSyxVQUFVLGlCQUFpQjtJQUNyQyxJQUFJLENBQUM7UUFDSCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUM1QixNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsY0FBYyxDQUFDLEVBQ2hELE9BQU8sQ0FDUixDQUNGLENBQUM7UUFFRixPQUFPLFdBQVcsQ0FBQyxPQUFPLENBQUM7SUFDN0IsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDWCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0FBQ0gsQ0FBQztBQWJELDhDQWFDO0FBcUJEOztHQUVHO0FBQ0gsTUFBYSxvQkFBb0I7SUFRL0IsWUFDRSxRQUFnQyxFQUNmLE1BQW9CO1FBQXBCLFdBQU0sR0FBTixNQUFNLENBQWM7UUFFckMsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxXQUFXLElBQUEsU0FBTSxHQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQy9ELElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSx5QkFBVyxFQUFFLENBQUM7UUFDaEMsSUFB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
@@ -1 +0,0 @@
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"}
@@ -1,25 +0,0 @@
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==
@@ -1 +0,0 @@
1
- {"version":3,"file":"VideoFrameExtractor.d.ts","sourceRoot":"","sources":["../../server/VideoFrameExtractor.ts"],"names":[],"mappings":";AAIA,KAAK,wBAAwB,GAAG,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhE;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAA6B;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAA6B;IAE5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAM;IAE3C,KAAK,EAAE,wBAAwB,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IAExB,OAAO,CAAC,MAAM,CAA2B;IAGzC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,YAAY,CAAqB;IAEzC,OAAO,CAAC,SAAS,CAAuB;IAExC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,OAAO,CAA4C;gBAGzD,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM;IAwBlB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,mBAAmB;IAmC3B;;;;;;;;OAQG;IACH,OAAO,CAAC,sCAAsC;IA0B9C,OAAO,CAAC,WAAW;IAyBN,QAAQ;IAyCrB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,WAAW;IAgBZ,OAAO;CAGf"}
@@ -1,148 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.VideoFrameExtractor = void 0;
4
- const telemetry_1 = require("@revideo/telemetry");
5
- const child_process_1 = require("child_process");
6
- /**
7
- * Walks through a video file and extracts frames.
8
- */
9
- class VideoFrameExtractor {
10
- constructor(filePath, startTime, fps, duration) {
11
- this.buffer = Buffer.alloc(0);
12
- // Images are buffered in memory until they are requested.
13
- this.imageBuffers = [];
14
- this.hooksWaiting = [];
15
- this.lastImage = null;
16
- this.state = 'processing';
17
- this.filePath = filePath;
18
- this.startTime = startTime;
19
- this.duration = duration;
20
- this.toTime = this.getEndTime(this.startTime);
21
- this.fps = fps;
22
- if (this.startTime >= this.duration) {
23
- this.process = this.createFfmpegProcessToExtractFirstFrame(filePath);
24
- return;
25
- }
26
- // Create a new ffmpeg process to extract the first 10 seconds of the video.
27
- this.process = this.createFfmpegProcess(this.startTime, this.toTime, this.filePath, this.fps);
28
- }
29
- getEndTime(startTime) {
30
- return Math.min(startTime + VideoFrameExtractor.chunkLengthInSeconds, this.duration);
31
- }
32
- createFfmpegProcess(startTime, toTime, filePath, fps) {
33
- const process = (0, child_process_1.spawn)('ffmpeg', [
34
- '-ss',
35
- startTime.toString(),
36
- '-to',
37
- toTime.toString(),
38
- '-i',
39
- filePath,
40
- '-vf',
41
- `fps=fps=${fps}`,
42
- '-f',
43
- 'image2pipe',
44
- '-vcodec',
45
- 'mjpeg',
46
- '-q:v',
47
- '2',
48
- '-',
49
- ], { stdio: ['ignore', 'pipe', 'inherit'] });
50
- process.stdout.on('data', this.processData.bind(this));
51
- process.on('close', this.handleClose.bind(this));
52
- process.on('error', this.handleError.bind(this));
53
- return process;
54
- }
55
- /**
56
- * We call this in the case that the time requested is greater than the
57
- * duration of the video. In this case, we want to display the first frame
58
- * of the video.
59
- *
60
- * Note: This does NOT match the behavior of the old implementation
61
- * inside of 2d/src/lib/components/Video.ts. In the old implementation, the
62
- * last frame is shown instead of the first frame.
63
- */
64
- createFfmpegProcessToExtractFirstFrame(filePath) {
65
- const process = (0, child_process_1.spawn)('ffmpeg', [
66
- '-i',
67
- filePath,
68
- '-vframes',
69
- '1',
70
- '-f',
71
- 'image2pipe',
72
- '-vcodec',
73
- 'mjpeg',
74
- '-q:v',
75
- '2',
76
- '-',
77
- ], { stdio: ['ignore', 'pipe', 'inherit'] });
78
- process.stdout.on('data', this.processData.bind(this));
79
- process.on('close', this.handleClose.bind(this));
80
- process.on('error', this.handleError.bind(this));
81
- return process;
82
- }
83
- processData(data) {
84
- this.buffer = Buffer.concat([this.buffer, data]);
85
- let start = 0;
86
- let end;
87
- // Look for JPEG_SOI and JPEG_EOI markers to extract full frames
88
- while ((start = this.buffer.indexOf(VideoFrameExtractor.jpegSOI, start)) !==
89
- -1 &&
90
- (end = this.buffer.indexOf(VideoFrameExtractor.jpegEOI, start)) !== -1) {
91
- end += 2; // Include the EOI marker itself
92
- const frame = this.buffer.subarray(start, end);
93
- this.imageBuffers.push(frame);
94
- this.hooksWaiting.forEach(hook => hook());
95
- this.hooksWaiting = [];
96
- this.buffer = this.buffer.subarray(end); // Remove the processed frame from buffer.
97
- start = 0;
98
- }
99
- }
100
- async popImage() {
101
- if (this.imageBuffers.length) {
102
- const image = this.imageBuffers.shift();
103
- this.lastImage = image;
104
- return image;
105
- }
106
- if (this.state === 'error') {
107
- throw new Error('An error occurred while extracting the video frames.');
108
- }
109
- // If the video is done and there are no more frames to extract, return the last frame.
110
- if (this.state === 'done' && this.toTime >= this.duration) {
111
- return this.lastImage;
112
- }
113
- // If there are more frames to extract, request the next chunk.
114
- if (this.state === 'done') {
115
- this.startTime = this.toTime;
116
- this.toTime = Math.min(this.startTime + VideoFrameExtractor.chunkLengthInSeconds, this.duration);
117
- this.process = this.createFfmpegProcess(this.startTime, this.toTime, this.filePath, this.fps);
118
- this.state = 'processing';
119
- }
120
- return await new Promise(res => {
121
- this.hooksWaiting.push(() => {
122
- res(this.imageBuffers.shift());
123
- });
124
- });
125
- }
126
- handleClose(code) {
127
- this.state = code === 0 ? 'done' : 'error';
128
- }
129
- handleError(err) {
130
- const code = err.code;
131
- if (code === 'ENOENT') {
132
- console.error('Error: ffmpeg not found. Make sure ffmpeg is installed on your system.');
133
- (0, telemetry_1.sendEvent)(telemetry_1.EventName.Error, { error: 'ffmpeg-not-found' });
134
- }
135
- else {
136
- console.error(`An ffmpeg error occurred while fetching frames from source video ${this.filePath}:`, err);
137
- (0, telemetry_1.sendEvent)(telemetry_1.EventName.Error, { error: 'ffmpeg-error', message: err.message });
138
- }
139
- }
140
- destroy() {
141
- this.process.kill();
142
- }
143
- }
144
- exports.VideoFrameExtractor = VideoFrameExtractor;
145
- VideoFrameExtractor.jpegSOI = Buffer.from([0xff, 0xd8]); // Start of Image marker
146
- VideoFrameExtractor.jpegEOI = Buffer.from([0xff, 0xd9]); // End of Image marker
147
- VideoFrameExtractor.chunkLengthInSeconds = 45;
148
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVmlkZW9GcmFtZUV4dHJhY3Rvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NlcnZlci9WaWRlb0ZyYW1lRXh0cmFjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGtEQUF3RDtBQUN4RCxpREFBeUQ7QUFLekQ7O0dBRUc7QUFDSCxNQUFhLG1CQUFtQjtJQXdCOUIsWUFDRSxRQUFnQixFQUNoQixTQUFpQixFQUNqQixHQUFXLEVBQ1gsUUFBZ0I7UUFuQlYsV0FBTSxHQUFXLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFekMsMERBQTBEO1FBQ2xELGlCQUFZLEdBQWEsRUFBRSxDQUFDO1FBQzVCLGlCQUFZLEdBQWtCLEVBQUUsQ0FBQztRQUVqQyxjQUFTLEdBQWtCLElBQUksQ0FBQztRQWV0QyxJQUFJLENBQUMsS0FBSyxHQUFHLFlBQVksQ0FBQztRQUMxQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUV6QixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBRWYsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNwQyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxzQ0FBc0MsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNyRSxPQUFPO1FBQ1QsQ0FBQztRQUVELDRFQUE0RTtRQUM1RSxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FDckMsSUFBSSxDQUFDLFNBQVMsRUFDZCxJQUFJLENBQUMsTUFBTSxFQUNYLElBQUksQ0FBQyxRQUFRLEVBQ2Is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
@@ -1,4 +0,0 @@
1
- import { Plugin } from '@revideo/vite-plugin/lib/plugins';
2
- declare const _default: () => Plugin;
3
- export default _default;
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
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"}