-
Notifications
You must be signed in to change notification settings - Fork 59
/
transcoder.js
83 lines (75 loc) · 2.66 KB
/
transcoder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
const child_process = require('child_process');
const fs = require('fs');
const path = require('path');
const AWS = require('aws-sdk');
const request = require('request');
const tempy = require('tempy');
const s3 = new AWS.S3();
exports.handler = (event, context, callback) => {
// We're going to do the transcoding asynchronously, so we callback immediately.
callback();
// Extract the event parameters.
const { mp3Key, url } = event;
const filename = event.filename || path.basename(mp3Key);
const logKey = event.logKey || `${mp3Key}.log`;
const s3Bucket = event.s3Bucket || 'youtube-mp3-downloader';
// Create temporary input/output filenames that we can clean up afterwards.
const inputFilename = tempy.file();
const mp3Filename = tempy.file({ extension: 'mp3' });
// Download the source file.
Promise.resolve().then(() => new Promise((resolve, revoke) => {
const writeStream = fs.createWriteStream(inputFilename);
writeStream.on('finish', resolve);
writeStream.on('error', revoke);
request(url).pipe(writeStream);
}))
// Perform the actual transcoding.
.then(() => {
// Use the Exodus ffmpeg bundled executable.
const ffmpeg = path.resolve(__dirname, 'exodus', 'bin', 'ffmpeg');
// Convert the FLV file to an MP3 file using ffmpeg.
const ffmpegArgs = [
'-i', inputFilename,
'-vn', // Disable the video stream in the output.
'-acodec', 'libmp3lame', // Use Lame for the mp3 encoding.
'-ac', '2', // Set 2 audio channels.
'-q:a', '6', // Set the quality to be roughly 128 kb/s.
mp3Filename,
];
const process = child_process.spawnSync(ffmpeg, ffmpegArgs);
return process.stdout.toString() + process.stderr.toString();
})
// Upload the generated MP3 to S3.
.then(logContent => new Promise((resolve, revoke) => {
s3.putObject({
Body: fs.createReadStream(mp3Filename),
Bucket: s3Bucket,
Key: mp3Key,
ContentDisposition: `attachment; filename="${filename.replace('"', '\'')}"`,
ContentType: 'audio/mpeg',
}, (error) => {
if (error) {
revoke(error);
} else {
// Update a log of the FFmpeg output.
const logFilename = path.basename(logKey);
s3.putObject({
Body: logContent,
Bucket: s3Bucket,
ContentType: 'text/plain',
ContentDisposition: `inline; filename="${logFilename.replace('"', '\'')}"`,
Key: logKey,
}, resolve);
}
})
}))
.catch(console.error)
// Delete the temporary files.
.then(() => {
[inputFilename, mp3Filename].forEach((filename) => {
if (fs.existsSync(filename)) {
fs.unlinkSync(filename);
}
});
});
};