@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
package/dist/utils.js ADDED
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVideoCodec = exports.getSampleRate = exports.checkForAudioStream = exports.mergeAudioWithVideo = exports.doesFileExist = exports.getVideoDuration = exports.createSilentAudioFile = exports.concatenateMedia = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const ffmpeg = require("fluent-ffmpeg");
6
+ const fs = require("fs");
7
+ const os = require("os");
8
+ const path = require("path");
9
+ const uuid_1 = require("uuid");
10
+ async function concatenateMedia(files, outputFile) {
11
+ const tempFile = path.join(os.tmpdir(), `${(0, uuid_1.v4)()}.txt`);
12
+ const fileContent = files
13
+ .map(file => `file '${file.replace(/'/g, "\\'")}'`)
14
+ .join('\n');
15
+ await fs.promises.writeFile(tempFile, fileContent);
16
+ return new Promise((resolve, reject) => {
17
+ // Return a new promise
18
+ const ffmpegCommand = ffmpeg();
19
+ ffmpegCommand
20
+ .input(tempFile)
21
+ .inputOptions(['-f concat', '-safe 0'])
22
+ .outputOptions(['-c copy'])
23
+ .on('error', err => {
24
+ console.error('Error:', err);
25
+ fs.promises.unlink(tempFile).catch(console.error);
26
+ reject(err); // Reject the promise on error
27
+ })
28
+ .on('end', () => {
29
+ fs.promises.unlink(tempFile).catch(console.error);
30
+ resolve(); // Resolve the promise on successful completion
31
+ })
32
+ .save(outputFile);
33
+ });
34
+ }
35
+ exports.concatenateMedia = concatenateMedia;
36
+ async function createSilentAudioFile(filePath, duration) {
37
+ return new Promise((resolve, reject) => {
38
+ ffmpeg()
39
+ .addInput(`anullsrc=channel_layout=stereo:sample_rate=${48000}`)
40
+ .inputFormat('lavfi')
41
+ .duration(duration)
42
+ .on('end', () => {
43
+ resolve(filePath);
44
+ })
45
+ .on('error', err => {
46
+ console.error('Error creating silent audio file:', err);
47
+ reject(err);
48
+ })
49
+ .save(filePath);
50
+ });
51
+ }
52
+ exports.createSilentAudioFile = createSilentAudioFile;
53
+ async function getVideoDuration(filePath) {
54
+ return new Promise((resolve, reject) => {
55
+ ffmpeg.ffprobe(filePath, (err, metadata) => {
56
+ if (err) {
57
+ reject(err);
58
+ return;
59
+ }
60
+ const duration = metadata.format.duration;
61
+ if (duration) {
62
+ resolve(duration);
63
+ }
64
+ else {
65
+ reject(new Error('Could not determine video duration.'));
66
+ }
67
+ });
68
+ });
69
+ }
70
+ exports.getVideoDuration = getVideoDuration;
71
+ async function doesFileExist(filePath) {
72
+ try {
73
+ await fs.promises.access(filePath, fs.constants.F_OK);
74
+ return true;
75
+ }
76
+ catch {
77
+ return false;
78
+ }
79
+ }
80
+ exports.doesFileExist = doesFileExist;
81
+ async function mergeAudioWithVideo(audioPath, videoPath, outputPath) {
82
+ return new Promise((resolve, reject) => {
83
+ ffmpeg()
84
+ .input(videoPath)
85
+ .input(audioPath)
86
+ .outputOptions(['-c:v', 'copy', '-c:a', 'aac', '-strict', 'experimental'])
87
+ .on('end', () => {
88
+ resolve();
89
+ })
90
+ .on('error', err => {
91
+ console.error(`Error merging video and audio: ${err.message}`);
92
+ reject(err);
93
+ })
94
+ .save(outputPath);
95
+ });
96
+ }
97
+ exports.mergeAudioWithVideo = mergeAudioWithVideo;
98
+ async function checkForAudioStream(file) {
99
+ return new Promise((resolve, reject) => {
100
+ ffmpeg.ffprobe(file, (err, metadata) => {
101
+ if (err) {
102
+ console.error(`error checking for audioStream for file ${file}`, err);
103
+ reject(err);
104
+ return;
105
+ }
106
+ const audioStreams = metadata.streams.filter(s => s.codec_type === 'audio');
107
+ resolve(audioStreams.length > 0);
108
+ });
109
+ });
110
+ }
111
+ exports.checkForAudioStream = checkForAudioStream;
112
+ async function getSampleRate(filePath) {
113
+ return new Promise((resolve, reject) => {
114
+ ffmpeg.ffprobe(filePath, (err, metadata) => {
115
+ if (err) {
116
+ reject(err);
117
+ return;
118
+ }
119
+ const audioStream = metadata.streams.find(s => s.codec_type === 'audio');
120
+ if (audioStream && audioStream.sample_rate) {
121
+ resolve(audioStream.sample_rate);
122
+ }
123
+ else {
124
+ reject(new Error('No audio stream found'));
125
+ }
126
+ });
127
+ });
128
+ }
129
+ exports.getSampleRate = getSampleRate;
130
+ async function getVideoCodec(filePath) {
131
+ return new Promise((resolve, reject) => {
132
+ const process = (0, child_process_1.spawn)('ffprobe', [
133
+ '-v',
134
+ 'error',
135
+ '-select_streams',
136
+ 'v:0',
137
+ '-show_entries',
138
+ 'stream=codec_name',
139
+ '-of',
140
+ 'default=nokey=1:noprint_wrappers=1',
141
+ filePath,
142
+ ]);
143
+ let output = '';
144
+ process.stdout.on('data', (data) => {
145
+ output += data.toString().trim();
146
+ });
147
+ process.on('close', (code) => {
148
+ if (code === 0) {
149
+ resolve(output);
150
+ }
151
+ else {
152
+ reject(new Error(`ffprobe exited with code ${code}`));
153
+ }
154
+ });
155
+ process.on('error', (error) => {
156
+ reject(error);
157
+ });
158
+ });
159
+ }
160
+ exports.getVideoCodec = getVideoCodec;
161
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsaURBQW9DO0FBQ3BDLHdDQUF3QztBQUN4Qyx5QkFBeUI7QUFDekIseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3QiwrQkFBa0M7QUFFM0IsS0FBSyxVQUFVLGdCQUFnQixDQUNwQyxLQUFlLEVBQ2YsVUFBa0I7SUFFbEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsR0FBRyxJQUFBLFNBQU0sR0FBRSxNQUFNLENBQUMsQ0FBQztJQUMzRCxNQUFNLFdBQVcsR0FBRyxLQUFLO1NBQ3RCLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQztTQUNsRCxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDZCxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUVuRCxPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ3JDLHVCQUF1QjtRQUN2QixNQUFNLGFBQWEsR0FBRyxNQUFNLEVBQUUsQ0FBQztRQUUvQixhQUFhO2FBQ1YsS0FBSyxDQUFDLFFBQVEsQ0FBQzthQUNmLFlBQVksQ0FBQyxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQzthQUN0QyxhQUFhLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQzthQUMxQixFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxFQUFFO1lBQ2pCLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQzdCLEVBQUUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxD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
@@ -4,8 +4,9 @@ type VideoFrameExtractorState = 'processing' | 'done' | 'error';
4
4
  * Walks through a video file and extracts frames.
5
5
  */
6
6
  export declare class VideoFrameExtractor {
7
- private static readonly jpegSOI;
8
- private static readonly jpegEOI;
7
+ private static readonly ffmpegPath;
8
+ private static readonly pngSignature;
9
+ private static readonly pngEOF;
9
10
  private static readonly chunkLengthInSeconds;
10
11
  state: VideoFrameExtractorState;
11
12
  filePath: string;
@@ -17,9 +18,11 @@ export declare class VideoFrameExtractor {
17
18
  private duration;
18
19
  private toTime;
19
20
  private fps;
21
+ private codec;
20
22
  private process;
21
23
  constructor(filePath: string, startTime: number, fps: number, duration: number);
22
24
  private getEndTime;
25
+ private getArgs;
23
26
  private createFfmpegProcess;
24
27
  /**
25
28
  * We call this in the case that the time requested is greater than the
@@ -38,4 +41,4 @@ export declare class VideoFrameExtractor {
38
41
  destroy(): void;
39
42
  }
40
43
  export {};
41
- //# sourceMappingURL=VideoFrameExtractor.d.ts.map
44
+ //# sourceMappingURL=video-frame-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-frame-extractor.d.ts","sourceRoot":"","sources":["../src/video-frame-extractor.ts"],"names":[],"mappings":";AAMA,KAAK,wBAAwB,GAAG,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhE;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CACgB;IAElD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAEjC;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAE3B;IAEH,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,KAAK,CAAuB;IACpC,OAAO,CAAC,OAAO,CAA0D;gBAGvE,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM;IAkClB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,OAAO;IA+Bf,OAAO,CAAC,mBAAmB;IAmB3B;;;;;;;;OAQG;IACH,OAAO,CAAC,sCAAsC;IAgB9C,OAAO,CAAC,WAAW;IAwBN,QAAQ;IAgDrB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,WAAW;IAgBZ,OAAO;CAGf"}
@@ -0,0 +1,160 @@
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
+ const pathToFfmpeg = require("ffmpeg-static");
7
+ const utils_1 = require("./utils");
8
+ /**
9
+ * Walks through a video file and extracts frames.
10
+ */
11
+ class VideoFrameExtractor {
12
+ constructor(filePath, startTime, fps, duration) {
13
+ this.buffer = Buffer.alloc(0);
14
+ // Images are buffered in memory until they are requested.
15
+ this.imageBuffers = [];
16
+ this.hooksWaiting = [];
17
+ this.lastImage = null;
18
+ this.codec = null;
19
+ this.process = null;
20
+ this.state = 'processing';
21
+ this.filePath = filePath;
22
+ this.startTime = startTime;
23
+ this.duration = duration;
24
+ this.toTime = this.getEndTime(this.startTime);
25
+ this.fps = fps;
26
+ if (this.startTime >= this.duration) {
27
+ (0, utils_1.getVideoCodec)(this.filePath).then(codec => {
28
+ this.process = this.createFfmpegProcessToExtractFirstFrame(filePath, codec);
29
+ });
30
+ return;
31
+ }
32
+ (0, utils_1.getVideoCodec)(this.filePath).then(codec => {
33
+ this.codec = codec;
34
+ // Create a new ffmpeg process to extract the first 10 seconds of the video.
35
+ this.process = this.createFfmpegProcess(this.startTime, this.toTime, this.filePath, this.fps, this.codec);
36
+ });
37
+ }
38
+ getEndTime(startTime) {
39
+ return Math.min(startTime + VideoFrameExtractor.chunkLengthInSeconds, this.duration);
40
+ }
41
+ getArgs(filePath, codec, range, fps) {
42
+ const args = [];
43
+ if (range) {
44
+ args.push('-ss', range[0].toString(), '-to', range[1].toString());
45
+ }
46
+ if (codec === 'vp9') {
47
+ args.push('-vcodec', 'libvpx-vp9');
48
+ }
49
+ args.push('-i', filePath);
50
+ if (fps) {
51
+ args.push('-vf', `fps=fps=${fps}`);
52
+ }
53
+ if (!range) {
54
+ args.push('-vframes', '1');
55
+ }
56
+ args.push('-f', 'image2pipe', '-vcodec', 'png', '-');
57
+ return args;
58
+ }
59
+ createFfmpegProcess(startTime, toTime, filePath, fps, codec) {
60
+ const args = this.getArgs(filePath, codec, [startTime, toTime], fps);
61
+ const process = (0, child_process_1.spawn)(VideoFrameExtractor.ffmpegPath, args, {
62
+ stdio: ['ignore', 'pipe', 'inherit'],
63
+ });
64
+ process.stdout.on('data', this.processData.bind(this));
65
+ process.on('close', this.handleClose.bind(this));
66
+ process.on('error', this.handleError.bind(this));
67
+ return process;
68
+ }
69
+ /**
70
+ * We call this in the case that the time requested is greater than the
71
+ * duration of the video. In this case, we want to display the first frame
72
+ * of the video.
73
+ *
74
+ * Note: This does NOT match the behavior of the old implementation
75
+ * inside of 2d/src/lib/components/Video.ts. In the old implementation, the
76
+ * last frame is shown instead of the first frame.
77
+ */
78
+ createFfmpegProcessToExtractFirstFrame(filePath, codec) {
79
+ const args = this.getArgs(filePath, codec);
80
+ const process = (0, child_process_1.spawn)(VideoFrameExtractor.ffmpegPath, args, {
81
+ stdio: ['ignore', 'pipe', 'ignore'],
82
+ });
83
+ process.stdout.on('data', this.processData.bind(this));
84
+ process.on('close', this.handleClose.bind(this));
85
+ process.on('error', this.handleError.bind(this));
86
+ return process;
87
+ }
88
+ processData(data) {
89
+ this.buffer = Buffer.concat([this.buffer, data]);
90
+ let start = 0;
91
+ let end;
92
+ while ((start = this.buffer.indexOf(VideoFrameExtractor.pngSignature, start)) !==
93
+ -1 &&
94
+ (end = this.buffer.indexOf(VideoFrameExtractor.pngEOF, start)) !== -1) {
95
+ end += VideoFrameExtractor.pngEOF.length;
96
+ const frame = this.buffer.subarray(start, end);
97
+ this.imageBuffers.push(frame);
98
+ this.hooksWaiting.forEach(hook => hook());
99
+ this.hooksWaiting = [];
100
+ this.buffer = this.buffer.subarray(end);
101
+ start = 0;
102
+ }
103
+ }
104
+ async popImage() {
105
+ if (this.imageBuffers.length) {
106
+ const image = this.imageBuffers.shift();
107
+ this.lastImage = image;
108
+ return image;
109
+ }
110
+ if (this.state === 'error') {
111
+ throw new Error('An error occurred while extracting the video frames.');
112
+ }
113
+ // If the video is done and there are no more frames to extract, return the last frame.
114
+ if (this.state === 'done' && this.toTime >= this.duration) {
115
+ return this.lastImage;
116
+ }
117
+ // If there are more frames to extract, request the next chunk.
118
+ if (this.state === 'done') {
119
+ this.startTime = this.toTime;
120
+ this.toTime = Math.min(this.startTime + VideoFrameExtractor.chunkLengthInSeconds, this.duration);
121
+ if (!this.codec) {
122
+ throw new Error("Can't extract frames without a codec. This error should never happen.");
123
+ }
124
+ this.process = this.createFfmpegProcess(this.startTime, this.toTime, this.filePath, this.fps, this.codec);
125
+ this.state = 'processing';
126
+ }
127
+ return await new Promise(res => {
128
+ this.hooksWaiting.push(() => {
129
+ res(this.imageBuffers.shift());
130
+ });
131
+ });
132
+ }
133
+ handleClose(code) {
134
+ this.state = code === 0 ? 'done' : 'error';
135
+ }
136
+ handleError(err) {
137
+ const code = err.code;
138
+ if (code === 'ENOENT') {
139
+ console.error('Error: ffmpeg not found. Make sure ffmpeg is installed on your system.');
140
+ (0, telemetry_1.sendEvent)(telemetry_1.EventName.Error, { error: 'ffmpeg-not-found' });
141
+ }
142
+ else {
143
+ console.error(`An ffmpeg error occurred while fetching frames from source video ${this.filePath}:`, err);
144
+ (0, telemetry_1.sendEvent)(telemetry_1.EventName.Error, { error: 'ffmpeg-error', message: err.message });
145
+ }
146
+ }
147
+ destroy() {
148
+ this.process?.kill();
149
+ }
150
+ }
151
+ exports.VideoFrameExtractor = VideoFrameExtractor;
152
+ VideoFrameExtractor.ffmpegPath = pathToFfmpeg || 'ffmpeg';
153
+ VideoFrameExtractor.pngSignature = Buffer.from([
154
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
155
+ ]);
156
+ VideoFrameExtractor.pngEOF = Buffer.from([
157
+ 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
158
+ ]);
159
+ VideoFrameExtractor.chunkLengthInSeconds = 45;
160
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlkZW8tZnJhbWUtZXh0cmFjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3ZpZGVvLWZyYW1lLWV4dHJhY3Rvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxrREFBd0Q7QUFDeEQsaURBQXlEO0FBQ3pELDhDQUE4QztBQUU5QyxtQ0FBc0M7QUFJdEM7O0dBRUc7QUFDSCxNQUFhLG1CQUFtQjtJQWdDOUIsWUFDRSxRQUFnQixFQUNoQixTQUFpQixFQUNqQixHQUFXLEVBQ1gsUUFBZ0I7UUFwQlYsV0FBTSxHQUFXLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFekMsMERBQTBEO1FBQ2xELGlCQUFZLEdBQWEsRUFBRSxDQUFDO1FBQzVCLGlCQUFZLEdBQWtCLEVBQUUsQ0FBQztRQUVqQyxjQUFTLEdBQWtCLElBQUksQ0FBQztRQU9oQyxVQUFLLEdBQWtCLElBQUksQ0FBQztRQUM1QixZQUFPLEdBQXFELElBQUksQ0FBQztRQVF2RSxJQUFJLENBQUMsS0FBSyxHQUFHLFlBQVksQ0FBQztRQUMxQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUV6QixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBRWYsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNwQyxJQUFBLHFCQUFhLEVBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDeEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsc0NBQXNDLENBQ3hELFFBQVEs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
package/package.json CHANGED
@@ -1,39 +1,28 @@
1
1
  {
2
2
  "name": "@revideo/ffmpeg",
3
- "version": "0.2.13",
4
- "description": "An FFmpeg video exporter for revideo",
5
- "main": "lib/server/index.js",
3
+ "version": "0.2.14-alpha.933+2129297",
4
+ "description": "Ffmpeg utilities for revideo",
5
+ "main": "dist/index.js",
6
6
  "author": "revideo",
7
7
  "homepage": "https://re.video/",
8
8
  "bugs": "https://github.com/havenhq/revideo/issues",
9
9
  "license": "MIT",
10
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"
11
+ "build": "tsc"
20
12
  },
21
13
  "files": [
22
- "lib"
14
+ "dist",
15
+ "types"
23
16
  ],
24
- "devDependencies": {
25
- "@types/fluent-ffmpeg": "^2.1.21"
26
- },
27
17
  "dependencies": {
28
- "@ffmpeg-installer/ffmpeg": "^1.1.0",
29
18
  "@ffprobe-installer/ffprobe": "^2.0.0",
30
- "@revideo/core": "0.2.13",
31
- "@revideo/telemetry": "0.2.13",
32
- "@revideo/vite-plugin": "0.2.13",
33
- "fluent-ffmpeg": "^2.1.2",
34
- "posthog-node": "^4.0.0",
35
- "uuid": "^9.0.1",
36
- "vite": "^4.5"
19
+ "@revideo/core": "^0.2.14-alpha.933+2129297",
20
+ "@revideo/telemetry": "^0.2.14-alpha.933+2129297",
21
+ "ffmpeg-static": "^5.2.0",
22
+ "fluent-ffmpeg": "^2.1.2"
23
+ },
24
+ "devDependencies": {
25
+ "@types/fluent-ffmpeg": "^2.1.21"
37
26
  },
38
- "gitHead": "26b0e890c4f8128028252cd3df1e45f9f209a7b7"
27
+ "gitHead": "2129297c5dde033fd30431ab92d3cfffa372326d"
39
28
  }
@@ -1,46 +0,0 @@
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
- private blobToDataUrl;
33
- stop(result: RendererResult): Promise<void>;
34
- kill(): Promise<void>;
35
- generateAudio(assets: AssetInfo[][], startFrame: number, endFrame: number): Promise<void>;
36
- mergeMedia(): Promise<void>;
37
- /**
38
- * Remotely invoke a method on the server and wait for a response.
39
- *
40
- * @param method - The method name to execute on the server.
41
- * @param data - The data that will be passed as an argument to the method.
42
- * Should be serializable.
43
- */
44
- private invoke;
45
- }
46
- //# sourceMappingURL=FFmpegExporterClient.d.ts.map
@@ -1 +0,0 @@
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;IA6BjD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IA7B3B,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;gBAYtD,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;YAepD,aAAa;IASd,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,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAIH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxC;;;;;;OAMG;IACH,OAAO,CAAC,MAAM;CA6Bf"}
@@ -1,118 +0,0 @@
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
- const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/jpeg'));
46
- if (!blob) {
47
- throw Error('Failed to convert canvas to Blob.');
48
- }
49
- const dataUrl = await this.blobToDataUrl(blob);
50
- await this.invoke('handleFrame', {
51
- data: dataUrl,
52
- });
53
- }
54
- async blobToDataUrl(blob) {
55
- return new Promise((resolve, reject) => {
56
- const reader = new FileReader();
57
- reader.onloadend = () => resolve(reader.result);
58
- reader.onerror = reject;
59
- reader.readAsDataURL(blob);
60
- });
61
- }
62
- async stop(result) {
63
- await this.invoke('end', result);
64
- }
65
- async kill() {
66
- await this.invoke('kill', {});
67
- }
68
- async generateAudio(assets, startFrame, endFrame) {
69
- await this.invoke('generateAudio', { assets, startFrame, endFrame });
70
- }
71
- async mergeMedia() {
72
- await this.invoke('mergeMedia', {});
73
- }
74
- /**
75
- * Remotely invoke a method on the server and wait for a response.
76
- *
77
- * @param method - The method name to execute on the server.
78
- * @param data - The data that will be passed as an argument to the method.
79
- * Should be serializable.
80
- */
81
- invoke(method, data) {
82
- if (import.meta.hot) {
83
- return new Promise((resolve, reject) => {
84
- const handle = (response) => {
85
- if (response.method !== method) {
86
- return;
87
- }
88
- _a.response.unsubscribe(handle);
89
- if (response.status === 'success') {
90
- resolve(response.data);
91
- }
92
- else {
93
- reject({
94
- message: `An error occurred while exporting the video: ${response.message}`,
95
- remarks: `Method: ${method}<br>Server error: ${response.message}`,
96
- object: data,
97
- });
98
- }
99
- };
100
- _a.response.subscribe(handle);
101
- import.meta.hot.send('revideo:ffmpeg-exporter', { method, data });
102
- });
103
- }
104
- else {
105
- throw new Error('FFmpegExporter can only be used locally.');
106
- }
107
- }
108
- }
109
- _a = FFmpegExporterClient;
110
- FFmpegExporterClient.id = '@revideo/ffmpeg';
111
- FFmpegExporterClient.displayName = 'Video (FFmpeg)';
112
- FFmpegExporterClient.response = new EventDispatcher();
113
- (() => {
114
- if (import.meta.hot) {
115
- import.meta.hot.on(`revideo:ffmpeg-exporter-ack`, (response) => _a.response.dispatch(response));
116
- }
117
- })();
118
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRkZtcGVnRXhwb3J0ZXJDbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9jbGllbnQvRkZtcGVnRXhwb3J0ZXJDbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQU9BLE9BQU8sRUFDTCxhQUFhLEVBQ2IsZUFBZSxFQUVmLGVBQWUsR0FFaEIsTUFBTSxlQUFlLENBQUM7QUFrQnZCOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sT0FBTyxvQkFBb0I7SUFJeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFnQjtRQUNqQyxPQUFPLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDM0MsU0FBUyxFQUFFLElBQUksYUFBYSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUM7WUFDaEQsWUFBWSxFQUFFLElBQUksYUFBYSxDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQzVELENBQUMsT0FBTyxDQUFDLEtBQUssQ0FDZjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFnQixFQUFFLFFBQTBCO1FBQ3JFLE9BQU8sSUFBSSxFQUFvQixDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBYUQsWUFDbUIsT0FBZ0IsRUFDaEIsUUFBMEI7UUFEMUIsWUFBTyxHQUFQLE9BQU8sQ0FBUztRQUNoQixhQUFRLEdBQVIsUUFBUSxDQUFrQjtJQUMxQyxDQUFDO0lBRUcsS0FBSyxDQUFDLEtBQUs7UUFDaEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBZ0MsQ0FBQztRQUN4RSxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1lBQ3pCLEdBQUcsSUFBSSxDQUFDLFFBQVE7WUFDaEIsR0FBRyxPQUFPO1lBQ1YsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLENB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
@@ -1,3 +0,0 @@
1
- declare const _default: () => import("@revideo/core").Plugin;
2
- export default _default;
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../client/index.ts"],"names":[],"mappings":";AAIA,wBAKG"}
@@ -1,9 +0,0 @@
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
@@ -1,22 +0,0 @@
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
- private videoFrameExtractors;
19
- private handleVideoFrameMessage;
20
- private handleRenderFinished;
21
- }
22
- //# sourceMappingURL=FFmpegBridge.d.ts.map
@@ -1 +0,0 @@
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;AAY1C;;;;;;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;IAOvC,OAAO,CAAC,aAAa,CAkCnB;IAEF,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,oBAAoB,CAA0C;IAEtE,OAAO,CAAC,uBAAuB,CAgC7B;IAEF,OAAO,CAAC,oBAAoB,CAG1B;CACH"}