-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathapp.js
152 lines (139 loc) · 5.22 KB
/
app.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
const dotenv = require('dotenv');
const AWS = require('aws-sdk');
const fs = require('fs');
const path = require('path');
const ffmpeg = require('fluent-ffmpeg');
ffmpeg.setFfmpegPath('/opt/local/bin/ffmpeg');
dotenv.config();
const s3 = new AWS.S3({
accessKeyId: process.env.ACCESS_KEY_ID,
secretAccessKey: process.env.SECRET_ACCESS_KEY
});
const mp4FileName = 'video1.mp4';
const bucketName = process.env.BUCKET_NAME;
const mp4Folder = 'mp4';
const hlsFolder = 'hls';
const main = async () => {
console.log('Starting script');
console.time('req_time');
try {
console.log('Downloading s3 mp4 file locally');
const mp4FilePath = `${mp4Folder}/${mp4FileName}`;
const writeStream = fs.createWriteStream('local.mp4');
const readStream = s3
.getObject({ Bucket: bucketName, Key: mp4FilePath })
.createReadStream();
readStream.pipe(writeStream);
await new Promise((resolve, reject) => {
writeStream.on('finish', resolve);
writeStream.on('error', reject);
});
console.log('Downloaded s3 mp4 file locally');
const resolutions = [
{
resolution: '320x180',
videoBitrate: '500k',
audioBitrate: '64k'
},
{
resolution: '854x480',
videoBitrate: '1000k',
audioBitrate: '128k'
},
{
resolution: '1280x720',
videoBitrate: '2500k',
audioBitrate: '192k'
}
];
const variantPlaylists = [];
for (const { resolution, videoBitrate, audioBitrate } of resolutions) {
console.log(`HLS conversion starting for ${resolution}`);
const outputFileName = `${mp4FileName.replace(
'.',
'_'
)}_${resolution}.m3u8`;
const segmentFileName = `${mp4FileName.replace(
'.',
'_'
)}_${resolution}_%03d.ts`;
await new Promise((resolve, reject) => {
ffmpeg('./local.mp4')
.outputOptions([
`-c:v h264`,
`-b:v ${videoBitrate}`,
`-c:a aac`,
`-b:a ${audioBitrate}`,
`-vf scale=${resolution}`,
`-f hls`,
`-hls_time 10`,
`-hls_list_size 0`,
`-hls_segment_filename hls/${segmentFileName}`
])
.output(`hls/${outputFileName}`)
.on('end', () => resolve())
.on('error', (err) => reject(err))
.run();
});
const variantPlaylist = {
resolution,
outputFileName
};
variantPlaylists.push(variantPlaylist);
console.log(`HLS conversion done for ${resolution}`);
}
console.log(`HLS master m3u8 playlist generating`);
let masterPlaylist = variantPlaylists
.map((variantPlaylist) => {
const { resolution, outputFileName } = variantPlaylist;
const bandwidth =
resolution === '320x180'
? 676800
: resolution === '854x480'
? 1353600
: 3230400;
return `#EXT-X-STREAM-INF:BANDWIDTH=${bandwidth},RESOLUTION=${resolution}\n${outputFileName}`;
})
.join('\n');
masterPlaylist = `#EXTM3U\n` + masterPlaylist;
const masterPlaylistFileName = `${mp4FileName.replace(
'.',
'_'
)}_master.m3u8`;
const masterPlaylistPath = `hls/${masterPlaylistFileName}`;
fs.writeFileSync(masterPlaylistPath, masterPlaylist);
console.log(`HLS master m3u8 playlist generated`);
console.log(`Deleting locally downloaded s3 mp4 file`);
fs.unlinkSync('local.mp4');
console.log(`Deleted locally downloaded s3 mp4 file`);
console.log(`Uploading media m3u8 playlists and ts segments to s3`);
const files = fs.readdirSync(hlsFolder);
for (const file of files) {
if (!file.startsWith(mp4FileName.replace('.', '_'))) {
continue;
}
const filePath = path.join(hlsFolder, file);
const fileStream = fs.createReadStream(filePath);
const uploadParams = {
Bucket: bucketName,
Key: `${hlsFolder}/${file}`,
Body: fileStream,
ContentType: file.endsWith('.ts')
? 'video/mp2t'
: file.endsWith('.m3u8')
? 'application/x-mpegURL'
: null
};
await s3.upload(uploadParams).promise();
fs.unlinkSync(filePath);
}
console.log(
`Uploaded media m3u8 playlists and ts segments to s3. Also deleted locally`
);
console.log('Success. Time taken: ');
console.timeEnd('req_time');
} catch (error) {
console.error('Error:', error);
}
};
main();