forked from Streampunk/beamcoder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjpeg_app.js
55 lines (46 loc) · 2.56 KB
/
jpeg_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
/*
Aerostat Beam Coder - Node.js native bindings for FFmpeg.
Copyright (C) 2019 Streampunk Media Ltd.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
https://www.streampunk.media/ mailto:furnace@streampunk.media
14 Ormiscaig, Aultbea, Achnasheen, IV22 2JJ U.K.
*/
/* Main example from the README.md. Run in a folder of media files.
Only supports 8-bit YUV 4:2:2 or 4:2:0 pixel formats.
*/
const beamcoder = require('../index.js'); // Use require('beamcoder') externally
const Koa = require('koa'); // Add koa to package.json dependencies
const app = new Koa();
app.use(async (ctx) => { // Assume HTTP GET with path /<file_name>/<time_in_s>
let parts = ctx.path.split('/'); // Split the path into filename and time
if ((parts.length < 3) || (isNaN(+parts[2]))) return; // Ignore favicon etc..
let dm = await beamcoder.demuxer('file:' + parts[1]); // Probe the file
await dm.seek({ time: +parts[2] }); // Seek to the closest keyframe to time
let packet = await dm.read(); // Find the next video packet (assumes stream 0)
for ( ; packet.stream_index !== 0 ; packet = await dm.read() );
let dec = beamcoder.decoder({ demuxer: dm, stream_index: 0 }); // Create a decoder
let decResult = await dec.decode(packet); // Decode the frame
if (decResult.frames.length === 0) // Frame may be buffered, so flush it out
decResult = await dec.flush();
// Filtering could be used to transform the picture here, e.g. scaling
let enc = beamcoder.encoder({ // Create an encoder for JPEG data
name : 'mjpeg', // FFmpeg does not have an encoder called 'jpeg'
width : dec.width,
height: dec.height,
pix_fmt: dec.pix_fmt.indexOf('422') >= 0 ? 'yuvj422p' : 'yuvj420p',
time_base: [1, 1] });
let jpegResult = await enc.encode(decResult.frames[0]); // Encode the frame
await enc.flush(); // Tidy the encoder
ctx.type = 'image/jpeg'; // Set the Content-Type of the data
ctx.body = jpegResult.packets[0].data; // Return the JPEG image data
});
app.listen(3000); // Start the server on port 3000