@twick/ffmpeg 0.11.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 +21 -0
- package/dist/ffmpeg-exporter-server.d.ts +26 -0
- package/dist/ffmpeg-exporter-server.d.ts.map +1 -0
- package/dist/ffmpeg-exporter-server.js +90 -0
- package/dist/generate-audio.d.ts +13 -0
- package/dist/generate-audio.d.ts.map +1 -0
- package/dist/generate-audio.js +195 -0
- package/dist/image-stream.d.ts +8 -0
- package/dist/image-stream.d.ts.map +1 -0
- package/dist/image-stream.js +25 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/settings.d.ts +22 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +56 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/utils.d.ts +21 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +232 -0
- package/dist/video-frame-extractor.d.ts +58 -0
- package/dist/video-frame-extractor.d.ts.map +1 -0
- package/dist/video-frame-extractor.js +265 -0
- package/package.json +31 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VideoFrameExtractor = void 0;
|
|
4
|
+
const telemetry_1 = require("@twick/telemetry");
|
|
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
|
+
const settings_1 = require("./settings");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
|
+
/**
|
|
13
|
+
* Walks through a video file and extracts frames.
|
|
14
|
+
*/
|
|
15
|
+
class VideoFrameExtractor {
|
|
16
|
+
constructor(filePath, startTime, fps, duration) {
|
|
17
|
+
this.ffmpegPath = settings_1.ffmpegSettings.getFfmpegPath();
|
|
18
|
+
this.buffer = Buffer.alloc(0);
|
|
19
|
+
this.bufferOffset = 0;
|
|
20
|
+
// Images are buffered in memory until they are requested.
|
|
21
|
+
this.imageBuffers = [];
|
|
22
|
+
this.lastImage = null;
|
|
23
|
+
this.framesProcessed = 0;
|
|
24
|
+
this.width = 0;
|
|
25
|
+
this.height = 0;
|
|
26
|
+
this.frameSize = 0;
|
|
27
|
+
this.codec = null;
|
|
28
|
+
this.process = null;
|
|
29
|
+
this.terminated = false;
|
|
30
|
+
this.state = 'processing';
|
|
31
|
+
this.filePath = filePath;
|
|
32
|
+
this.downloadedFilePath = VideoFrameExtractor.downloadedVideoMap.get(filePath)?.localPath;
|
|
33
|
+
this.startTimeOffset = VideoFrameExtractor.downloadedVideoMap.get(filePath)
|
|
34
|
+
?.startTimeOffset;
|
|
35
|
+
this.startTime = startTime;
|
|
36
|
+
this.duration = duration;
|
|
37
|
+
this.toTime = this.getEndTime(this.startTime);
|
|
38
|
+
this.fps = fps;
|
|
39
|
+
(0, utils_1.getVideoMetadata)(this.downloadedFilePath).then(metadata => {
|
|
40
|
+
this.width = metadata.width;
|
|
41
|
+
this.height = metadata.height;
|
|
42
|
+
this.frameSize = this.width * this.height * 4;
|
|
43
|
+
this.buffer = Buffer.alloc(this.frameSize);
|
|
44
|
+
this.codec = metadata.codec;
|
|
45
|
+
if (this.startTime >= this.duration) {
|
|
46
|
+
this.process = this.createFfmpegProcessToExtractFirstFrame(this.downloadedFilePath, this.codec);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.process = this.createFfmpegProcess(this.startTime - this.startTimeOffset, this.toTime, this.downloadedFilePath, this.fps, this.codec);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
static downloadVideoChunk(url, startTime, endTime) {
|
|
53
|
+
const outputDir = path.join(os.tmpdir(), `twick-decoder-chunks`);
|
|
54
|
+
if (!fs.existsSync(outputDir)) {
|
|
55
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
ffmpeg.ffprobe(url, (err, metadata) => {
|
|
59
|
+
if (err) {
|
|
60
|
+
reject(err);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const format = metadata.format.format_name?.split(',')[-1] || 'mp4';
|
|
64
|
+
const outputFileName = `chunk_${(0, uuid_1.v4)()}.${format}`;
|
|
65
|
+
const outputPath = path.join(outputDir, outputFileName);
|
|
66
|
+
const toleranceInSeconds = 0.5;
|
|
67
|
+
const adjustedStartTime = Math.max(startTime - toleranceInSeconds, 0);
|
|
68
|
+
ffmpeg(url)
|
|
69
|
+
.setFfmpegPath(settings_1.ffmpegSettings.getFfmpegPath())
|
|
70
|
+
.inputOptions([
|
|
71
|
+
`-ss ${adjustedStartTime}`,
|
|
72
|
+
`-to ${endTime + toleranceInSeconds}`,
|
|
73
|
+
])
|
|
74
|
+
.outputOptions(['-c copy'])
|
|
75
|
+
.output(outputPath)
|
|
76
|
+
.on('end', () => {
|
|
77
|
+
this.downloadedVideoMap.set(url, {
|
|
78
|
+
localPath: outputPath,
|
|
79
|
+
startTimeOffset: adjustedStartTime,
|
|
80
|
+
});
|
|
81
|
+
resolve(outputPath);
|
|
82
|
+
})
|
|
83
|
+
.on('error', err => reject(err))
|
|
84
|
+
.run();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
getTime() {
|
|
89
|
+
return this.startTime + this.framesProcessed / this.fps;
|
|
90
|
+
}
|
|
91
|
+
getLastTime() {
|
|
92
|
+
return this.startTime + (this.framesProcessed - 1) / this.fps;
|
|
93
|
+
}
|
|
94
|
+
getLastFrame() {
|
|
95
|
+
return this.lastImage;
|
|
96
|
+
}
|
|
97
|
+
getWidth() {
|
|
98
|
+
return this.width;
|
|
99
|
+
}
|
|
100
|
+
getHeight() {
|
|
101
|
+
return this.height;
|
|
102
|
+
}
|
|
103
|
+
getEndTime(startTime) {
|
|
104
|
+
return Math.min(startTime + VideoFrameExtractor.chunkLengthInSeconds, this.duration);
|
|
105
|
+
}
|
|
106
|
+
getArgs(codec, range, fps) {
|
|
107
|
+
const inputOptions = [];
|
|
108
|
+
const outputOptions = [];
|
|
109
|
+
inputOptions.push('-loglevel', settings_1.ffmpegSettings.getLogLevel());
|
|
110
|
+
if (range) {
|
|
111
|
+
inputOptions.push(...['-ss', range[0].toFixed(2), '-to', range[1].toFixed(2)]);
|
|
112
|
+
}
|
|
113
|
+
if (codec === 'vp9') {
|
|
114
|
+
inputOptions.push('-vcodec', 'libvpx-vp9');
|
|
115
|
+
}
|
|
116
|
+
if (fps) {
|
|
117
|
+
outputOptions.push('-vf', `fps=fps=${fps}`);
|
|
118
|
+
}
|
|
119
|
+
if (!range) {
|
|
120
|
+
outputOptions.push('-vframes', '1');
|
|
121
|
+
}
|
|
122
|
+
outputOptions.push('-f', 'rawvideo');
|
|
123
|
+
outputOptions.push('-pix_fmt', 'rgba');
|
|
124
|
+
return { inputOptions, outputOptions };
|
|
125
|
+
}
|
|
126
|
+
createFfmpegProcess(startTime, toTime, filePath, fps, codec) {
|
|
127
|
+
const { inputOptions, outputOptions } = this.getArgs(codec, [startTime, toTime], fps);
|
|
128
|
+
const process = ffmpeg(filePath)
|
|
129
|
+
.setFfmpegPath(this.ffmpegPath)
|
|
130
|
+
.inputOptions(inputOptions)
|
|
131
|
+
.outputOptions(outputOptions)
|
|
132
|
+
.on('end', () => {
|
|
133
|
+
this.handleClose(0);
|
|
134
|
+
})
|
|
135
|
+
.on('error', err => {
|
|
136
|
+
this.handleError(err);
|
|
137
|
+
})
|
|
138
|
+
.on('stderr', stderrLine => {
|
|
139
|
+
console.log(stderrLine);
|
|
140
|
+
})
|
|
141
|
+
.on('stdout', stderrLine => {
|
|
142
|
+
console.log(stderrLine);
|
|
143
|
+
});
|
|
144
|
+
const ffstream = process.pipe();
|
|
145
|
+
ffstream.on('data', (data) => {
|
|
146
|
+
this.processData(data);
|
|
147
|
+
});
|
|
148
|
+
return process;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* We call this in the case that the time requested is greater than the
|
|
152
|
+
* duration of the video. In this case, we want to display the first frame
|
|
153
|
+
* of the video.
|
|
154
|
+
*
|
|
155
|
+
* Note: This does NOT match the behavior of the old implementation
|
|
156
|
+
* inside of 2d/src/lib/components/Video.ts. In the old implementation, the
|
|
157
|
+
* last frame is shown instead of the first frame.
|
|
158
|
+
*/
|
|
159
|
+
createFfmpegProcessToExtractFirstFrame(filePath, codec) {
|
|
160
|
+
const { inputOptions, outputOptions } = this.getArgs(codec, undefined, undefined);
|
|
161
|
+
const process = ffmpeg(filePath)
|
|
162
|
+
.setFfmpegPath(this.ffmpegPath)
|
|
163
|
+
.inputOptions(inputOptions)
|
|
164
|
+
.outputOptions(outputOptions)
|
|
165
|
+
.on('end', () => {
|
|
166
|
+
this.handleClose(0);
|
|
167
|
+
})
|
|
168
|
+
.on('error', err => {
|
|
169
|
+
this.handleError(err);
|
|
170
|
+
})
|
|
171
|
+
.on('stderr', stderrLine => {
|
|
172
|
+
console.log(stderrLine);
|
|
173
|
+
})
|
|
174
|
+
.on('stdout', stderrLine => {
|
|
175
|
+
console.log(stderrLine);
|
|
176
|
+
});
|
|
177
|
+
const ffstream = process.pipe();
|
|
178
|
+
ffstream.on('data', (data) => {
|
|
179
|
+
this.processData(data);
|
|
180
|
+
});
|
|
181
|
+
return process;
|
|
182
|
+
}
|
|
183
|
+
processData(data) {
|
|
184
|
+
let dataOffset = 0;
|
|
185
|
+
while (dataOffset < data.length) {
|
|
186
|
+
const remainingSpace = this.frameSize - this.bufferOffset;
|
|
187
|
+
const chunkSize = Math.min(remainingSpace, data.length - dataOffset);
|
|
188
|
+
data.copy(this.buffer, this.bufferOffset, dataOffset, dataOffset + chunkSize);
|
|
189
|
+
this.bufferOffset += chunkSize;
|
|
190
|
+
dataOffset += chunkSize;
|
|
191
|
+
// We have a complete frame
|
|
192
|
+
if (this.bufferOffset === this.frameSize) {
|
|
193
|
+
this.imageBuffers.push(Buffer.from(this.buffer)); // Create a copy
|
|
194
|
+
this.bufferOffset = 0; // Reset buffer for next frame
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async popImage() {
|
|
199
|
+
if (this.imageBuffers.length) {
|
|
200
|
+
const image = this.imageBuffers.shift();
|
|
201
|
+
this.framesProcessed++;
|
|
202
|
+
this.lastImage = image;
|
|
203
|
+
return image;
|
|
204
|
+
}
|
|
205
|
+
if (this.state === 'error') {
|
|
206
|
+
throw new Error('An error occurred while extracting the video frames.');
|
|
207
|
+
}
|
|
208
|
+
// If the video is done and there are no more frames to extract, return the last frame.
|
|
209
|
+
if (this.state === 'done' && this.toTime >= this.duration) {
|
|
210
|
+
return this.lastImage;
|
|
211
|
+
}
|
|
212
|
+
// If there are more frames to extract, request the next chunk.
|
|
213
|
+
if (this.state === 'done') {
|
|
214
|
+
this.startTime = this.toTime;
|
|
215
|
+
this.toTime = Math.min(this.startTime + VideoFrameExtractor.chunkLengthInSeconds, this.duration);
|
|
216
|
+
if (!this.codec) {
|
|
217
|
+
throw new Error("Can't extract frames without a codec. This error should never happen.");
|
|
218
|
+
}
|
|
219
|
+
this.process = this.createFfmpegProcess(this.startTime, this.toTime, this.downloadedFilePath, this.fps, this.codec);
|
|
220
|
+
this.state = 'processing';
|
|
221
|
+
}
|
|
222
|
+
while (this.imageBuffers.length < 1) {
|
|
223
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
224
|
+
}
|
|
225
|
+
const image = this.imageBuffers.shift();
|
|
226
|
+
this.framesProcessed++;
|
|
227
|
+
this.lastImage = image;
|
|
228
|
+
return image;
|
|
229
|
+
}
|
|
230
|
+
handleClose(code) {
|
|
231
|
+
this.state = code === 0 ? 'done' : 'error';
|
|
232
|
+
}
|
|
233
|
+
async handleError(err) {
|
|
234
|
+
const code = err.code;
|
|
235
|
+
if (this.terminated) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (code === 'ENOENT') {
|
|
239
|
+
(0, telemetry_1.sendEvent)(telemetry_1.EventName.Error, { error: 'ffmpeg-not-found' });
|
|
240
|
+
throw new Error('Error: ffmpeg not found. Make sure ffmpeg is installed on your system.');
|
|
241
|
+
}
|
|
242
|
+
else if (err.message.includes('SIGSEGV')) {
|
|
243
|
+
(0, telemetry_1.sendEvent)(telemetry_1.EventName.Error, {
|
|
244
|
+
error: 'ffmpeg-sigsegv',
|
|
245
|
+
message: err.message,
|
|
246
|
+
});
|
|
247
|
+
throw new Error(`Error: Segmentation fault when running ffmpeg. This is a common issue on Linux, you might be able to fix it by installing nscd ('sudo apt-get install nscd'). For more information, see https://docs.re.video/common-issues/ffmpeg/`);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
await (0, telemetry_1.sendEvent)(telemetry_1.EventName.Error, {
|
|
251
|
+
error: 'ffmpeg-error',
|
|
252
|
+
message: err.message,
|
|
253
|
+
});
|
|
254
|
+
throw new Error(`An ffmpeg error occurred while fetching frames from source video ${this.filePath}: ${err}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
destroy() {
|
|
258
|
+
this.terminated = true;
|
|
259
|
+
this.process?.kill('SIGTERM');
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
exports.VideoFrameExtractor = VideoFrameExtractor;
|
|
263
|
+
VideoFrameExtractor.chunkLengthInSeconds = 5;
|
|
264
|
+
VideoFrameExtractor.downloadedVideoMap = new Map();
|
|
265
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlkZW8tZnJhbWUtZXh0cmFjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3ZpZGVvLWZyYW1lLWV4dHJhY3Rvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxnREFBc0Q7QUFDdEQsd0NBQXdDO0FBQ3hDLHlCQUF5QjtBQUN6Qix5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLCtCQUFrQztBQUNsQyx5Q0FBMEM7QUFDMUMsbUNBQXlDO0FBSXpDOztHQUVHO0FBQ0gsTUFBYSxtQkFBbUI7SUFtQzlCLFlBQ0UsUUFBZ0IsRUFDaEIsU0FBaUIsRUFDakIsR0FBVyxFQUNYLFFBQWdCO1FBcENELGVBQVUsR0FBRyx5QkFBYyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBTXJELFdBQU0sR0FBVyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pDLGlCQUFZLEdBQVcsQ0FBQyxDQUFDO1FBRWpDLDBEQUEwRDtRQUNsRCxpQkFBWSxHQUFhLEVBQUUsQ0FBQztRQUM1QixjQUFTLEdBQWtCLElBQUksQ0FBQztRQU9oQyxvQkFBZSxHQUFXLENBQUMsQ0FBQztRQUU1QixVQUFLLEdBQVcsQ0FBQyxDQUFDO1FBQ2xCLFdBQU0sR0FBVyxDQUFDLENBQUM7UUFDbkIsY0FBUyxHQUFXLENBQUMsQ0FBQztRQUN0QixVQUFLLEdBQWtCLElBQUksQ0FBQztRQUM1QixZQUFPLEdBQWdDLElBQUksQ0FBQztRQUM1QyxlQUFVLEdBQVksS0FBSyxDQUFDO1FBYWxDLElBQUksQ0FBQyxLQUFLLEdBQUcsWUFBWSxDQUFDO1FBQzFCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQ2xFLFFBQVEsQ0FDVCxFQUFFLFNBQW1CLENBQUM7UUFDdkIsSUFBSSxDQUFDLGVBQWUsR0FBRyxtQkFBbUIsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO1lBQ3pFLEVBQUUsZUFBeUIsQ0FBQztRQUU5QixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBRWYsSUFBQSx3QkFBZ0IsRUFBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDeEQsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDO1lBQzVCLElBQUksQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQztZQUM5QixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMzQyxJQUFJLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUM7WUFFNUIsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDcEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsc0NBQXNDLENBQ3hELElBQUksQ0FBQyxrQkFBa0IsRUFDdkIsSUFBSSxDQUFDLEtBQUssQ0FDWCxDQUFDO2dCQUNGLE9BQU87WUFDVCxDQUFDO1lBRUQsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQ3JDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFDckMsSUFBSSxDQUFDLE1BQU0sRUFDWCxJQUFJLENBQUMsa0JBQWtCLEVBQ3ZCLElBQUksQ0FBQyxHQUFHLEVBQ1IsSUFBSSxDQUFDLEtBQUssQ0FDWCxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sTUFBTSxDQUFDLGtCQUFrQixDQUM5QixHQUFXLEVBQ1gsU0FBaUIsRUFDakIsT0FBZTtRQUVmLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLHNCQUFzQixDQUFDLENBQUM7UUFDakUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUM5QixFQUFFLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRSxFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFFRCxPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLFFBQVEsRUFBRSxFQUFFO2dCQUNwQyxJQUFJLEdBQUcsRUFBRSxDQUFDO29CQUNSLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDWixPQUFPO2dCQUNULENBQUM7Z0JBRUQsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDO2dCQUNwRSxNQUFNLGNBQWMsR0FBRyxTQUFTLElBQUEsU0FBTSxHQUFFLElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQ3JELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGNBQWMsQ0FBQyxDQUFDO2dCQUN4RCxNQUFNLGtCQUFrQixHQUFHLEdBQUcsQ0FBQztnQkFFL0IsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsR0FBRyxrQkFBa0IsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFFdEUsTUFBTSxDQUFDLEdBQUcsQ0FBQztxQkFDUixhQUFhLENBQUMseUJBQWMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztxQkFDN0MsWUFBWSxDQUFDO29CQUNaLE9BQU8saUJBQWlCLEVBQUU7b0JBQzFCLE9BQU8sT0FBTyxHQUFHLGtCQUFrQixFQUFFO2lCQUN0QyxDQUFDO3FCQUNELGFBQWEsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO3FCQUMxQixNQUFNLENBQUMsVUFBVSxDQUFDO3FCQUNsQixFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRTtvQkFDZCxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTt3QkFDL0IsU0FBUyxFQUFFLFVBQVU7d0JBQ3JCLGVBQWUsRUFBRSxpQkFBaUI7cUJBQ25DLENBQUMsQ0FBQztvQkFDSCxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ3RCLENBQUMsQ0FBQztxQkFDRCxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO3FCQUMvQixHQUFHLEVBQUUsQ0FBQztZQUNYLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sT0FBTztRQUNaLE9BQU8sSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUM7SUFDMUQsQ0FBQztJQUVNLFdBQVc7UUFDaEIsT0FBTyxJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQ2hFLENBQUM7SUFFTSxZQUFZO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUN4QixDQUFDO0lBRU0sUUFBUTtRQUNiLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0lBRU0sU0FBUztRQUNkLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRU8sVUFBVSxDQUFDLFNBQWlCO1FBQ2xDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FDYixTQUFTLEdBQUcsbUJBQW1CLENBQUMsb0JBQW9CLEVBQ3BELElBQUksQ0FBQyxRQUFRLENBQ2QsQ0FBQztJQUNKLENBQUM7SUFFTyxPQUFPLENBQ2IsS0FBYSxFQUNiLEtBQXdCLEVBQ3hCLEdBQVk7UUFFWixNQUFNLFlBQVksR0FBRyxFQUFFLENBQUM7UUFDeEIsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO1FBRXpCLFlBQVksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLHlCQUFjLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUU3RCxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1YsWUFBWSxDQUFDLElBQUksQ0FDZixHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FDNUQsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLEtBQUssS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUNwQixZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUM3QyxDQUFDO1FBRUQsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNSLGFBQWEsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFdBQVcsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBRUQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsYUFBYSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDdEMsQ0FBQztRQUVELGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ3JDLGFBQWEsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRXZDLE9BQU8sRUFBQyxZQUFZLEVBQUUsYUFBYSxFQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVPLG1CQUFtQixDQUN6QixTQUFpQixFQUNqQixNQUFjLEVBQ2QsUUFBZ0IsRUFDaEIsR0FBVyxFQUNYLEtBQWE7UUFFYixNQUFNLEVBQUMsWUFBWSxFQUFFLGFBQWEsRUFBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQ2hELEtBQUssRUFDTCxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsRUFDbkIsR0FBRyxDQUNKLENBQUM7UUFFRixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO2FBQzdCLGFBQWEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO2FBQzlCLFlBQVksQ0FBQyxZQUFZLENBQUM7YUFDMUIsYUFBYSxDQUFDLGFBQWEsQ0FBQzthQUM1QixFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEIsQ0FBQyxDQUFDO2FBQ0QsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsRUFBRTtZQUNqQixJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3hCLENBQUMsQ0FBQzthQUNELEVBQUUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLEVBQUU7WUFDekIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMxQixDQUFDLENBQUM7YUFDRCxFQUFFLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxFQUFFO1lBQ3pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDMUIsQ0FBQyxDQUFDLENBQUM7UUFFTCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFZLEVBQUUsRUFBRTtZQUNuQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pCLENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ssc0NBQXNDLENBQzVDLFFBQWdCLEVBQ2hCLEtBQWE7UUFFYixNQUFNLEVBQUMsWUFBWSxFQUFFLGFBQWEsRUFBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQ2hELEtBQUssRUFDTCxTQUFTLEVBQ1QsU0FBUyxDQUNWLENBQUM7UUFFRixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO2FBQzdCLGFBQWEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO2FBQzlCLFlBQVksQ0FBQyxZQUFZLENBQUM7YUFDMUIsYUFBYSxDQUFDLGFBQWEsQ0FBQzthQUM1QixFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEIsQ0FBQyxDQUFDO2FBQ0QsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsRUFBRTtZQUNqQixJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3hCLENBQUMsQ0FBQzthQUNELEVBQUUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLEVBQUU7WUFDekIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMxQixDQUFDLENBQUM7YUFDRCxFQUFFLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxFQUFFO1lBQ3pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDMUIsQ0FBQyxDQUFDLENBQUM7UUFFTCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFZLEVBQUUsRUFBRTtZQUNuQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pCLENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVPLFdBQVcsQ0FBQyxJQUFZO1FBQzlCLElBQUksVUFBVSxHQUFHLENBQUMsQ0FBQztRQUVuQixPQUFPLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDaEMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1lBQzFELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDLENBQUM7WUFFckUsSUFBSSxDQUFDLElBQUksQ0FDUCxJQUFJLENBQUMsTUFBTSxFQUNYLElBQUksQ0FBQyxZQUFZLEVBQ2pCLFVBQVUsRUFDVixVQUFVLEdBQUcsU0FBUyxDQUN2QixDQUFDO1lBQ0YsSUFBSSxDQUFDLFlBQVksSUFBSSxTQUFTLENBQUM7WUFDL0IsVUFBVSxJQUFJLFNBQVMsQ0FBQztZQUV4QiwyQkFBMkI7WUFDM0IsSUFBSSxJQUFJLENBQUMsWUFBWSxLQUFLLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDekMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQjtnQkFDbEUsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUMsQ0FBQyw4QkFBOEI7WUFDdkQsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLFFBQVE7UUFDbkIsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzdCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFHLENBQUM7WUFDekMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1lBQ3ZCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUM7UUFDMUUsQ0FBQztRQUVELHVGQUF1RjtRQUN2RixJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzFELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUN4QixDQUFDO1FBRUQsK0RBQStEO1FBQy9ELElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7WUFDN0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUNwQixJQUFJLENBQUMsU0FBUyxHQUFHLG1CQUFtQixDQUFDLG9CQUFvQixFQUN6RCxJQUFJLENBQUMsUUFBUSxDQUNkLENBQUM7WUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNoQixNQUFNLElBQUksS0FBSyxDQUNiLHVFQUF1RSxDQUN4RSxDQUFDO1lBQ0osQ0FBQztZQUVELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUNyQyxJQUFJLENBQUMsU0FBUyxFQUNkLElBQUksQ0FBQyxNQUFNLEVBQ1gsSUFBSSxDQUFDLGtCQUFrQixFQUN2QixJQUFJLENBQUMsR0FBRyxFQUNSLElBQUksQ0FBQyxLQUFLLENBQ1gsQ0FBQztZQUVGLElBQUksQ0FBQyxLQUFLLEdBQUcsWUFBWSxDQUFDO1FBQzVCLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDeEQsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFHLENBQUM7UUFDekMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVPLFdBQVcsQ0FBQyxJQUFZO1FBQzlCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7SUFDN0MsQ0FBQztJQUVPLEtBQUssQ0FBQyxXQUFXLENBQUMsR0FBUTtRQUNoQyxNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBRXRCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDdEIsSUFBQSxxQkFBUyxFQUFDLHFCQUFTLENBQUMsS0FBSyxFQUFFLEVBQUMsS0FBSyxFQUFFLGtCQUFrQixFQUFDLENBQUMsQ0FBQztZQUN4RCxNQUFNLElBQUksS0FBSyxDQUNiLHdFQUF3RSxDQUN6RSxDQUFDO1FBQ0osQ0FBQzthQUFNLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUMzQyxJQUFBLHFCQUFTLEVBQUMscUJBQVMsQ0FBQyxLQUFLLEVBQUU7Z0JBQ3pCLEtBQUssRUFBRSxnQkFBZ0I7Z0JBQ3ZCLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTzthQUNyQixDQUFDLENBQUM7WUFDSCxNQUFNLElBQUksS0FBSyxDQUNiLHFPQUFxTyxDQUN0TyxDQUFDO1FBQ0osQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLElBQUEscUJBQVMsRUFBQyxxQkFBUyxDQUFDLEtBQUssRUFBRTtnQkFDL0IsS0FBSyxFQUFFLGNBQWM7Z0JBQ3JCLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTzthQUNyQixDQUFDLENBQUM7WUFDSCxNQUFNLElBQUksS0FBSyxDQUNiLG9FQUFvRSxJQUFJLENBQUMsUUFBUSxLQUFLLEdBQUcsRUFBRSxDQUM1RixDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFTSxPQUFPO1FBQ1osSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDdkIsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDaEMsQ0FBQzs7QUE3WEgsa0RBOFhDO0FBN1h5Qix3Q0FBb0IsR0FBRyxDQUFDLEFBQUosQ0FBSztBQTZCbkMsc0NBQWtCLEdBRzVCLElBQUksR0FBRyxFQUFFLEFBSG1CLENBR2xCIn0=
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@twick/ffmpeg",
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "Ffmpeg utilities for twick",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"author": "twick",
|
|
7
|
+
"homepage": "https://re.video/",
|
|
8
|
+
"bugs": "https://github.com/ncounterspecialist/twick-base/issues",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"types"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
19
|
+
"@ffprobe-installer/ffprobe": "^2.0.0",
|
|
20
|
+
"@twick/core": "^0.11.0",
|
|
21
|
+
"@twick/telemetry": "^0.11.0",
|
|
22
|
+
"fluent-ffmpeg": "^2.1.2",
|
|
23
|
+
"uuid": "^10.0.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/ffprobe-static": "^2.0.3",
|
|
27
|
+
"@types/fluent-ffmpeg": "^2.1.21",
|
|
28
|
+
"@types/uuid": "^10.0.0"
|
|
29
|
+
},
|
|
30
|
+
"gitHead": "59f38f4e7d3a9a30943bbad830dc0201eaa57ce7"
|
|
31
|
+
}
|