@lumen5/beamcoder 0.0.21 → 0.0.23
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/package.json +1 -1
- package/.circleci/config.yml +0 -41
- package/.circleci/images/testbeam10-4.1/Dockerfile +0 -12
- package/.circleci/test_image/Dockerfile +0 -14
- package/.circleci/test_image/build.md +0 -13
- package/.github/workflows/prebuild.yml +0 -118
- package/examples/encode_h264.js +0 -92
- package/examples/jpeg_app.js +0 -55
- package/examples/jpeg_filter_app.js +0 -101
- package/examples/make_mp4.js +0 -123
- package/images/beamcoder_small.jpg +0 -0
- package/prebuilds/@lumen5/beamcoder-v0.0.21-node-v127-darwin-arm64.tar.gz +0 -0
- package/prebuilds/@lumen5/beamcoder-v0.0.21-node-v127-linux-x64.tar.gz +0 -0
- package/scratch/decode_aac.js +0 -38
- package/scratch/decode_avci.js +0 -50
- package/scratch/decode_hevc.js +0 -38
- package/scratch/decode_pcm.js +0 -39
- package/scratch/make_a_mux.js +0 -68
- package/scratch/muxer.js +0 -74
- package/scratch/read_wav.js +0 -35
- package/scratch/simple_mux.js +0 -39
- package/scratch/stream_avci.js +0 -127
- package/scratch/stream_mp4.js +0 -78
- package/scratch/stream_mux.js +0 -47
- package/scratch/stream_pcm.js +0 -82
- package/scratch/stream_wav.js +0 -62
- package/test/codecParamsSpec.js +0 -148
- package/test/decoderSpec.js +0 -56
- package/test/demuxerSpec.js +0 -41
- package/test/encoderSpec.js +0 -69
- package/test/filtererSpec.js +0 -47
- package/test/formatSpec.js +0 -343
- package/test/frameSpec.js +0 -145
- package/test/introspectionSpec.js +0 -73
- package/test/muxerSpec.js +0 -34
- package/test/packetSpec.js +0 -122
package/package.json
CHANGED
package/.circleci/config.yml
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
jobs:
|
|
3
|
-
build:
|
|
4
|
-
working_directory: ~/Streampunk/beamcoder
|
|
5
|
-
parallelism: 1
|
|
6
|
-
shell: /bin/bash --login
|
|
7
|
-
environment:
|
|
8
|
-
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
|
|
9
|
-
CIRCLE_TEST_REPORTS: /tmp/circleci-test-results
|
|
10
|
-
UV_THREADPOOL_SIZE: 16
|
|
11
|
-
docker:
|
|
12
|
-
- image: streampunkmedia/testbeam:16-5.0
|
|
13
|
-
steps:
|
|
14
|
-
- checkout
|
|
15
|
-
- run: mkdir -p $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS
|
|
16
|
-
- restore_cache:
|
|
17
|
-
keys:
|
|
18
|
-
# This branch if available
|
|
19
|
-
- v2-dep-{{ .Branch }}-
|
|
20
|
-
# Default branch if not
|
|
21
|
-
- v2-dep-master-
|
|
22
|
-
# Any branch if there are none on the default branch - this should be unnecessary if you have your default branch configured correctly
|
|
23
|
-
- v2-dep-
|
|
24
|
-
- run: npm install tap-xunit
|
|
25
|
-
- run: npm install --unsafe-perm
|
|
26
|
-
- save_cache:
|
|
27
|
-
key: v2-dep-{{ .Branch }}-{{ epoch }}
|
|
28
|
-
paths:
|
|
29
|
-
- ./node_modules
|
|
30
|
-
- run: echo 'export PATH="~/Streampunk/beamcoder/node_modules/.bin:$PATH"' >> $BASH_ENV
|
|
31
|
-
- run: mkdir -p $CIRCLE_TEST_REPORTS/eslint
|
|
32
|
-
- run: mkdir -p $CIRCLE_TEST_REPORTS/xunit
|
|
33
|
-
- run: eslint '**/*.js' -f junit -o /tmp/circleci-test-results/eslint/eslint.xml
|
|
34
|
-
- run: set -eo pipefail && npm test | tap-xunit > /tmp/circleci-test-results/xunit/results.xml
|
|
35
|
-
|
|
36
|
-
- store_test_results:
|
|
37
|
-
path: /tmp/circleci-test-results
|
|
38
|
-
- store_artifacts:
|
|
39
|
-
path: /tmp/circleci-artifacts
|
|
40
|
-
- store_artifacts:
|
|
41
|
-
path: /tmp/circleci-test-results
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
FROM circleci/node:10
|
|
2
|
-
|
|
3
|
-
# install OpenCL driver
|
|
4
|
-
RUN sudo apt-get update \
|
|
5
|
-
&& sudo apt-get install software-properties-common \
|
|
6
|
-
&& sudo add-apt-repository ppa:jonathonf/ffmpeg-4 \
|
|
7
|
-
&& sudo apt-get update \
|
|
8
|
-
&& sudo apt-get install libavcodec-dev libavformat-dev libavdevice-dev libavfilter-dev libavutil-dev libpostproc-dev libswresample-dev libswscale-dev
|
|
9
|
-
|
|
10
|
-
# delete all the apt list files since they're big and get stale quickly
|
|
11
|
-
RUN sudo rm -rf /var/lib/apt/lists/*
|
|
12
|
-
# this forces "apt-get update" in dependent images, which is also good
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
FROM cimg/node:16.14
|
|
2
|
-
|
|
3
|
-
# install FFmpeg
|
|
4
|
-
RUN sudo apt-get update \
|
|
5
|
-
&& sudo apt-get install software-properties-common \
|
|
6
|
-
&& sudo add-apt-repository ppa:savoury1/ffmpeg4 \
|
|
7
|
-
&& sudo add-apt-repository ppa:savoury1/ffmpeg5 \
|
|
8
|
-
&& sudo apt-get update \
|
|
9
|
-
&& sudo apt-get upgrade && sudo apt-get dist-upgrade \
|
|
10
|
-
&& sudo apt-get install libavcodec-dev libavformat-dev libavdevice-dev libavfilter-dev libavutil-dev libpostproc-dev libswresample-dev libswscale-dev
|
|
11
|
-
|
|
12
|
-
# delete all the apt list files since they're big and get stale quickly
|
|
13
|
-
RUN sudo rm -rf /var/lib/apt/lists/*
|
|
14
|
-
# this forces "apt-get update" in dependent images, which is also good
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Instructions for building the CircleCI docker image for testing
|
|
2
|
-
|
|
3
|
-
- install docker desktop
|
|
4
|
-
- cd to this directory
|
|
5
|
-
- docker build -t streampunkmedia/testbeam:x-y.z .
|
|
6
|
-
- run container locally to check build
|
|
7
|
-
- push to Docker Hub
|
|
8
|
-
- update config.yml to pull new version tag
|
|
9
|
-
- push to git to trigger new build and test
|
|
10
|
-
|
|
11
|
-
(x: NodeAPI base version, y.z: FFmpeg build number)
|
|
12
|
-
|
|
13
|
-
See https://circleci.com/developer/images/image/cimg/node for CircleCI docker image tags
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# Build prebuilt binaries and publish to npm
|
|
2
|
-
name: Build & Publish
|
|
3
|
-
|
|
4
|
-
on:
|
|
5
|
-
push:
|
|
6
|
-
# branches: [main]
|
|
7
|
-
pull_request:
|
|
8
|
-
branches: [main]
|
|
9
|
-
workflow_dispatch:
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
prebuild:
|
|
13
|
-
strategy:
|
|
14
|
-
matrix:
|
|
15
|
-
include:
|
|
16
|
-
- os: ubuntu-22.04
|
|
17
|
-
platform: linux
|
|
18
|
-
- os: macos-14
|
|
19
|
-
platform: darwin
|
|
20
|
-
runs-on: ${{ matrix.os }}
|
|
21
|
-
steps:
|
|
22
|
-
- uses: actions/checkout@v3
|
|
23
|
-
|
|
24
|
-
- uses: actions/setup-node@v3
|
|
25
|
-
with:
|
|
26
|
-
node-version: 22
|
|
27
|
-
|
|
28
|
-
- name: Get package version
|
|
29
|
-
id: version
|
|
30
|
-
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
|
|
31
|
-
|
|
32
|
-
- name: Install system dependencies (Linux)
|
|
33
|
-
if: matrix.platform == 'linux'
|
|
34
|
-
run: sudo apt-get update && sudo apt-get install -y libvpx-dev
|
|
35
|
-
|
|
36
|
-
- name: Install system dependencies (macOS)
|
|
37
|
-
if: matrix.platform == 'darwin'
|
|
38
|
-
run: brew install libvpx
|
|
39
|
-
|
|
40
|
-
- name: Install dependencies (skip native build)
|
|
41
|
-
run: yarn install --frozen-lockfile --ignore-scripts
|
|
42
|
-
|
|
43
|
-
- name: Download FFmpeg static libraries
|
|
44
|
-
run: node install_ffmpeg_static.js
|
|
45
|
-
|
|
46
|
-
- name: Build prebuild
|
|
47
|
-
run: npx prebuild --strip -r node -t 22.0.0
|
|
48
|
-
env:
|
|
49
|
-
FFMPEG_STATIC: "1"
|
|
50
|
-
|
|
51
|
-
- name: List prebuilds
|
|
52
|
-
run: find prebuilds -name "*.tar.gz" -ls
|
|
53
|
-
|
|
54
|
-
- name: Upload prebuild artifact
|
|
55
|
-
uses: actions/upload-artifact@v4
|
|
56
|
-
with:
|
|
57
|
-
name: prebuild-${{ matrix.platform }}
|
|
58
|
-
path: prebuilds/**/*.tar.gz
|
|
59
|
-
|
|
60
|
-
release:
|
|
61
|
-
needs: prebuild
|
|
62
|
-
runs-on: ubuntu-latest
|
|
63
|
-
steps:
|
|
64
|
-
- uses: actions/checkout@v3
|
|
65
|
-
|
|
66
|
-
- uses: actions/setup-node@v3
|
|
67
|
-
with:
|
|
68
|
-
node-version: 22
|
|
69
|
-
registry-url: https://registry.npmjs.org/
|
|
70
|
-
|
|
71
|
-
- name: Get package version
|
|
72
|
-
id: version
|
|
73
|
-
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
|
|
74
|
-
|
|
75
|
-
- name: Download all prebuild artifacts
|
|
76
|
-
uses: actions/download-artifact@v4
|
|
77
|
-
with:
|
|
78
|
-
path: prebuilds
|
|
79
|
-
pattern: prebuild-*
|
|
80
|
-
merge-multiple: true
|
|
81
|
-
|
|
82
|
-
- name: List all prebuilds
|
|
83
|
-
run: find prebuilds -name "*.tar.gz" -ls
|
|
84
|
-
|
|
85
|
-
- name: Create or update release
|
|
86
|
-
# if: github.ref == 'refs/heads/main'
|
|
87
|
-
run: |
|
|
88
|
-
VERSION="v${{ steps.version.outputs.version }}"
|
|
89
|
-
# Check if release exists
|
|
90
|
-
if gh release view "$VERSION" >/dev/null 2>&1; then
|
|
91
|
-
echo "Release $VERSION exists, uploading prebuilds..."
|
|
92
|
-
else
|
|
93
|
-
echo "Creating release $VERSION..."
|
|
94
|
-
gh release create "$VERSION" --title "$VERSION" --notes "Prebuilt binaries for version $VERSION"
|
|
95
|
-
fi
|
|
96
|
-
# Upload prebuilds
|
|
97
|
-
find prebuilds -name "*.tar.gz" -exec gh release upload "$VERSION" {} --clobber \;
|
|
98
|
-
env:
|
|
99
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
100
|
-
|
|
101
|
-
- name: Install system dependencies
|
|
102
|
-
run: sudo apt-get update && sudo apt-get install -y libvpx-dev
|
|
103
|
-
|
|
104
|
-
- name: Install dependencies (skip native build)
|
|
105
|
-
run: yarn install --frozen-lockfile --ignore-scripts
|
|
106
|
-
|
|
107
|
-
- name: Download FFmpeg static libraries
|
|
108
|
-
run: node install_ffmpeg_static.js
|
|
109
|
-
|
|
110
|
-
- name: Build for npm publish
|
|
111
|
-
# if: github.ref == 'refs/heads/main'
|
|
112
|
-
run: FFMPEG_STATIC=1 npx node-gyp rebuild
|
|
113
|
-
|
|
114
|
-
- name: Publish to npm
|
|
115
|
-
# if: github.ref == 'refs/heads/main'
|
|
116
|
-
run: npm publish
|
|
117
|
-
env:
|
|
118
|
-
NODE_AUTH_TOKEN: ${{ secrets.npm_token }}
|
package/examples/encode_h264.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Aerostat Beam Coder - Node.js native bindings for FFmpeg.
|
|
3
|
-
Copyright (C) 2019 Streampunk Media Ltd.
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify
|
|
6
|
-
it under the terms of the GNU General Public License as published by
|
|
7
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
(at your option) any later version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful,
|
|
11
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License
|
|
16
|
-
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
https://www.streampunk.media/ mailto:furnace@streampunk.media
|
|
19
|
-
14 Ormiscaig, Aultbea, Achnasheen, IV22 2JJ U.K.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/* Generate a 200 frame test pattern and encode it as a raw H.264 file.
|
|
23
|
-
|
|
24
|
-
Usage: node encode_h264.js <filename.h264>
|
|
25
|
-
|
|
26
|
-
Output can be viewed in VLC. Make sure "All Files" is selected to see the file.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
const beamcoder = require('../index.js'); // Use require('beamcoder') externally
|
|
30
|
-
const fs = require('fs');
|
|
31
|
-
|
|
32
|
-
let endcode = Buffer.from([0, 0, 1, 0xb7]);
|
|
33
|
-
|
|
34
|
-
async function run() {
|
|
35
|
-
let start = process.hrtime();
|
|
36
|
-
let encParams = {
|
|
37
|
-
name: 'libx264',
|
|
38
|
-
width: 1920,
|
|
39
|
-
height: 1080,
|
|
40
|
-
bit_rate: 2000000,
|
|
41
|
-
time_base: [1, 25],
|
|
42
|
-
framerate: [25, 1],
|
|
43
|
-
gop_size: 10,
|
|
44
|
-
max_b_frames: 1,
|
|
45
|
-
pix_fmt: 'yuv420p',
|
|
46
|
-
priv_data: { preset: 'slow' }
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
let encoder = beamcoder.encoder(encParams);
|
|
50
|
-
console.log('Encoder', encoder);
|
|
51
|
-
|
|
52
|
-
let outFile = fs.createWriteStream(process.argv[2]);
|
|
53
|
-
|
|
54
|
-
for ( let i = 0 ; i < 200 ; i++ ) {
|
|
55
|
-
let frame = beamcoder.frame({
|
|
56
|
-
width: encParams.width,
|
|
57
|
-
height: encParams.height,
|
|
58
|
-
format: encParams.pix_fmt
|
|
59
|
-
}).alloc();
|
|
60
|
-
|
|
61
|
-
let linesize = frame.linesize;
|
|
62
|
-
let [ ydata, bdata, cdata ] = frame.data;
|
|
63
|
-
frame.pts = i;
|
|
64
|
-
|
|
65
|
-
for ( let y = 0 ; y < frame.height ; y++ ) {
|
|
66
|
-
for ( let x = 0 ; x < linesize[0] ; x++ ) {
|
|
67
|
-
ydata[y * linesize[0] + x] = x + y + i * 3;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
for ( let y = 0 ; y < frame.height / 2 ; y++) {
|
|
72
|
-
for ( let x = 0; x < linesize[1] ; x++) {
|
|
73
|
-
bdata[y * linesize[1] + x] = 128 + y + i * 2;
|
|
74
|
-
cdata[y * linesize[1] + x] = 64 + x + i * 5;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
let packets = await encoder.encode(frame);
|
|
79
|
-
if ( i % 10 === 0) console.log('Encoding frame', i);
|
|
80
|
-
packets.packets.forEach(x => outFile.write(x.data));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
let p2 = await encoder.flush();
|
|
84
|
-
console.log('Flushing', p2.packets.length, 'frames.');
|
|
85
|
-
p2.packets.forEach(x => outFile.write(x.data));
|
|
86
|
-
outFile.end(endcode);
|
|
87
|
-
|
|
88
|
-
console.log('Total time ', process.hrtime(start));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (typeof process.argv[2] === 'string') { run(); }
|
|
92
|
-
else { console.error('Error: Please provide a file name.'); }
|
package/examples/jpeg_app.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Aerostat Beam Coder - Node.js native bindings for FFmpeg.
|
|
3
|
-
Copyright (C) 2019 Streampunk Media Ltd.
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify
|
|
6
|
-
it under the terms of the GNU General Public License as published by
|
|
7
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
(at your option) any later version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful,
|
|
11
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License
|
|
16
|
-
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
https://www.streampunk.media/ mailto:furnace@streampunk.media
|
|
19
|
-
14 Ormiscaig, Aultbea, Achnasheen, IV22 2JJ U.K.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/* Main example from the README.md. Run in a folder of media files.
|
|
23
|
-
|
|
24
|
-
Only supports 8-bit YUV 4:2:2 or 4:2:0 pixel formats.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
const beamcoder = require('../index.js'); // Use require('beamcoder') externally
|
|
28
|
-
const Koa = require('koa'); // Add koa to package.json dependencies
|
|
29
|
-
const app = new Koa();
|
|
30
|
-
|
|
31
|
-
app.use(async (ctx) => { // Assume HTTP GET with path /<file_name>/<time_in_s>
|
|
32
|
-
let parts = ctx.path.split('/'); // Split the path into filename and time
|
|
33
|
-
if ((parts.length < 3) || (isNaN(+parts[2]))) return; // Ignore favicon etc..
|
|
34
|
-
let dm = await beamcoder.demuxer('file:' + parts[1]); // Probe the file
|
|
35
|
-
await dm.seek({ time: +parts[2] }); // Seek to the closest keyframe to time
|
|
36
|
-
let packet = await dm.read(); // Find the next video packet (assumes stream 0)
|
|
37
|
-
for ( ; packet.stream_index !== 0 ; packet = await dm.read() );
|
|
38
|
-
let dec = beamcoder.decoder({ demuxer: dm, stream_index: 0 }); // Create a decoder
|
|
39
|
-
let decResult = await dec.decode(packet); // Decode the frame
|
|
40
|
-
if (decResult.frames.length === 0) // Frame may be buffered, so flush it out
|
|
41
|
-
decResult = await dec.flush();
|
|
42
|
-
// Filtering could be used to transform the picture here, e.g. scaling
|
|
43
|
-
let enc = beamcoder.encoder({ // Create an encoder for JPEG data
|
|
44
|
-
name : 'mjpeg', // FFmpeg does not have an encoder called 'jpeg'
|
|
45
|
-
width : dec.width,
|
|
46
|
-
height: dec.height,
|
|
47
|
-
pix_fmt: dec.pix_fmt.indexOf('422') >= 0 ? 'yuvj422p' : 'yuvj420p',
|
|
48
|
-
time_base: [1, 1] });
|
|
49
|
-
let jpegResult = await enc.encode(decResult.frames[0]); // Encode the frame
|
|
50
|
-
await enc.flush(); // Tidy the encoder
|
|
51
|
-
ctx.type = 'image/jpeg'; // Set the Content-Type of the data
|
|
52
|
-
ctx.body = jpegResult.packets[0].data; // Return the JPEG image data
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
app.listen(3000); // Start the server on port 3000
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Aerostat Beam Coder - Node.js native bindings for FFmpeg.
|
|
3
|
-
Copyright (C) 2019 Streampunk Media Ltd.
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify
|
|
6
|
-
it under the terms of the GNU General Public License as published by
|
|
7
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
(at your option) any later version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful,
|
|
11
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License
|
|
16
|
-
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
https://www.streampunk.media/ mailto:furnace@streampunk.media
|
|
19
|
-
14 Ormiscaig, Aultbea, Achnasheen, IV22 2JJ U.K.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/* Main example from the README.md with added filtering. Run in a folder of media files.
|
|
23
|
-
|
|
24
|
-
Will convert source pixel formats to 8-bit YUV 4:2:2
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
const beamcoder = require('../index.js'); // Use require('beamcoder') externally
|
|
28
|
-
const Koa = require('koa'); // Add koa to package.json dependencies
|
|
29
|
-
const app = new Koa();
|
|
30
|
-
|
|
31
|
-
app.use(async (ctx) => { // Assume HTTP GET with path /<file_name>/<time_in_s>
|
|
32
|
-
let parts = ctx.path.split('/'); // Split the path into filename and time
|
|
33
|
-
if ((parts.length < 3) || (isNaN(+parts[2]))) return; // Ignore favicon etc..
|
|
34
|
-
let dm = await beamcoder.demuxer('file:' + parts[1]); // Probe the file
|
|
35
|
-
await dm.seek({ time: +parts[2] }); // Seek to the closest keyframe to time
|
|
36
|
-
let packet = await dm.read(); // Find the next video packet (assumes stream 0)
|
|
37
|
-
for ( ; packet.stream_index !== 0 ; packet = await dm.read() );
|
|
38
|
-
let dec = beamcoder.decoder({ demuxer: dm, stream_index: 0 }); // Create a decoder
|
|
39
|
-
let decResult = await dec.decode(packet); // Decode the frame
|
|
40
|
-
if (decResult.frames.length === 0) // Frame may be buffered, so flush it out
|
|
41
|
-
decResult = await dec.flush();
|
|
42
|
-
|
|
43
|
-
// audio test
|
|
44
|
-
const aindex = 2;
|
|
45
|
-
const audStr = dm.streams[aindex];
|
|
46
|
-
// console.log(audStr);
|
|
47
|
-
let adec = beamcoder.decoder({ demuxer: dm, stream_index: aindex }); // Create a decoder
|
|
48
|
-
// console.log(adec);
|
|
49
|
-
let apkt = await dm.read();
|
|
50
|
-
let afrm = await adec.decode(apkt);
|
|
51
|
-
console.log(afrm.frames);
|
|
52
|
-
const audEnc = beamcoder.encoder({
|
|
53
|
-
name: 'aac',
|
|
54
|
-
sample_fmt: 'fltp',
|
|
55
|
-
sample_rate: 48000,
|
|
56
|
-
channels: 1,
|
|
57
|
-
channel_layout: 'mono', });
|
|
58
|
-
|
|
59
|
-
const audFilt = await beamcoder.filterer({ // Create a filterer for audio
|
|
60
|
-
filterType: 'audio',
|
|
61
|
-
inputParams: [{
|
|
62
|
-
sampleRate: audStr.codecpar.sample_rate,
|
|
63
|
-
sampleFormat: adec.sample_fmt,
|
|
64
|
-
channelLayout: audStr.codecpar.channel_layout,
|
|
65
|
-
timeBase: audStr.time_base }],
|
|
66
|
-
outputParams: [{
|
|
67
|
-
sampleRate: 1024,
|
|
68
|
-
sampleFormat: 'fltp',
|
|
69
|
-
channelLayout: 'mono' }],
|
|
70
|
-
filterSpec: 'aresample=1024' });
|
|
71
|
-
|
|
72
|
-
const audFiltPkt = await audFilt.filter([{ frames: afrm }]);
|
|
73
|
-
const encPkt = await audEnc.encode(audFiltPkt[0].frames[0]);
|
|
74
|
-
console.log(encPkt);
|
|
75
|
-
|
|
76
|
-
let vstr = dm.streams[0]; // Select the video stream (assumes stream 0)
|
|
77
|
-
let filt = await beamcoder.filterer({ // Create a filterer for video
|
|
78
|
-
filterType: 'video',
|
|
79
|
-
inputParams: [{
|
|
80
|
-
width: vstr.codecpar.width,
|
|
81
|
-
height: vstr.codecpar.height,
|
|
82
|
-
pixelFormat: vstr.codecpar.format,
|
|
83
|
-
timeBase: vstr.time_base,
|
|
84
|
-
pixelAspect: vstr.sample_aspect_ratio }],
|
|
85
|
-
outputParams: [{ pixelFormat: 'yuv422p' }],
|
|
86
|
-
filterSpec: 'scale=640:360, colorspace=range=jpeg:all=bt709' });
|
|
87
|
-
let filtResult = await filt.filter([{ frames: decResult }]); // Filter the frame
|
|
88
|
-
let filtFrame = filtResult[0].frames[0];
|
|
89
|
-
let enc = beamcoder.encoder({ // Create an encoder for JPEG data
|
|
90
|
-
name : 'mjpeg', // FFmpeg does not have an encoder called 'jpeg'
|
|
91
|
-
width : filtFrame.width,
|
|
92
|
-
height: filtFrame.height,
|
|
93
|
-
pix_fmt: 'yuvj422p',
|
|
94
|
-
time_base: [1, 1] });
|
|
95
|
-
let jpegResult = await enc.encode(filtFrame); // Encode the filtered frame
|
|
96
|
-
await enc.flush(); // Tidy the encoder
|
|
97
|
-
ctx.type = 'image/jpeg'; // Set the Content-Type of the data
|
|
98
|
-
ctx.body = jpegResult.packets[0].data; // Return the JPEG image data
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
app.listen(3000); // Start the server on port 3000
|
package/examples/make_mp4.js
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Aerostat Beam Coder - Node.js native bindings for FFmpeg.
|
|
3
|
-
Copyright (C) 2019 Streampunk Media Ltd.
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify
|
|
6
|
-
it under the terms of the GNU General Public License as published by
|
|
7
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
(at your option) any later version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful,
|
|
11
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License
|
|
16
|
-
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
https://www.streampunk.media/ mailto:furnace@streampunk.media
|
|
19
|
-
14 Ormiscaig, Aultbea, Achnasheen, IV22 2JJ U.K.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/* Generate a 200 frame test pattern and encode it as a raw H.264 file.
|
|
23
|
-
|
|
24
|
-
Usage: node encode_h264.js <filename.h264>
|
|
25
|
-
|
|
26
|
-
Output can be viewed in VLC. Make sure "All Files" is selected to see the file.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
const beamcoder = require('../index.js'); // Use require('beamcoder') externally
|
|
30
|
-
const fs = require('fs');
|
|
31
|
-
|
|
32
|
-
let endcode = Buffer.from([0, 0, 1, 0xb7]);
|
|
33
|
-
|
|
34
|
-
async function run() {
|
|
35
|
-
let start = process.hrtime();
|
|
36
|
-
let encParams = {
|
|
37
|
-
name: 'libx264',
|
|
38
|
-
width: 1920,
|
|
39
|
-
height: 1080,
|
|
40
|
-
bit_rate: 2000000,
|
|
41
|
-
time_base: [1, 25],
|
|
42
|
-
framerate: [25, 1],
|
|
43
|
-
gop_size: 10,
|
|
44
|
-
max_b_frames: 1,
|
|
45
|
-
pix_fmt: 'yuv420p',
|
|
46
|
-
priv_data: { preset: 'slow' }
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
let encoder = await beamcoder.encoder(encParams);
|
|
50
|
-
console.log('Encoder', encoder);
|
|
51
|
-
|
|
52
|
-
const mux = beamcoder.muxer({ format_name: 'mp4' });
|
|
53
|
-
let vstr = mux.newStream({
|
|
54
|
-
name: 'h264',
|
|
55
|
-
time_base: [1, 90000],
|
|
56
|
-
interleaved: true }); // Set to false for manual interleaving, true for automatic
|
|
57
|
-
Object.assign(vstr.codecpar, {
|
|
58
|
-
width: 1920,
|
|
59
|
-
height: 1080,
|
|
60
|
-
format: 'yuv420p'
|
|
61
|
-
});
|
|
62
|
-
console.log(vstr);
|
|
63
|
-
await mux.openIO({
|
|
64
|
-
url: 'file:test.mp4'
|
|
65
|
-
});
|
|
66
|
-
await mux.writeHeader();
|
|
67
|
-
|
|
68
|
-
let outFile = fs.createWriteStream(process.argv[2]);
|
|
69
|
-
|
|
70
|
-
for ( let i = 0 ; i < 200 ; i++ ) {
|
|
71
|
-
let frame = beamcoder.frame({
|
|
72
|
-
width: encParams.width,
|
|
73
|
-
height: encParams.height,
|
|
74
|
-
format: encParams.pix_fmt
|
|
75
|
-
}).alloc();
|
|
76
|
-
|
|
77
|
-
let linesize = frame.linesize;
|
|
78
|
-
let [ ydata, bdata, cdata ] = frame.data;
|
|
79
|
-
frame.pts = i+100;
|
|
80
|
-
|
|
81
|
-
for ( let y = 0 ; y < frame.height ; y++ ) {
|
|
82
|
-
for ( let x = 0 ; x < linesize[0] ; x++ ) {
|
|
83
|
-
ydata[y * linesize[0] + x] = x + y + i * 3;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
for ( let y = 0 ; y < frame.height / 2 ; y++) {
|
|
88
|
-
for ( let x = 0; x < linesize[1] ; x++) {
|
|
89
|
-
bdata[y * linesize[1] + x] = 128 + y + i * 2;
|
|
90
|
-
cdata[y * linesize[1] + x] = 64 + x + i * 5;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
let packets = await encoder.encode(frame);
|
|
95
|
-
if ( i % 10 === 0) console.log('Encoding frame', i);
|
|
96
|
-
for (const pkt of packets.packets) {
|
|
97
|
-
pkt.duration = 1;
|
|
98
|
-
pkt.stream_index = vstr.index;
|
|
99
|
-
pkt.pts = pkt.pts * 90000/25;
|
|
100
|
-
pkt.dts = pkt.dts * 90000/25;
|
|
101
|
-
await mux.writeFrame(pkt);
|
|
102
|
-
outFile.write(pkt.data);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
let p2 = await encoder.flush();
|
|
107
|
-
console.log('Flushing', p2.packets.length, 'frames.');
|
|
108
|
-
for (const pkt of p2.packets) {
|
|
109
|
-
pkt.duration = 1;
|
|
110
|
-
pkt.stream_index = vstr.index;
|
|
111
|
-
pkt.pts = pkt.pts * 90000/25;
|
|
112
|
-
pkt.dts = pkt.dts * 90000/25;
|
|
113
|
-
await mux.writeFrame(pkt);
|
|
114
|
-
outFile.write(pkt.data);
|
|
115
|
-
}
|
|
116
|
-
await mux.writeTrailer();
|
|
117
|
-
outFile.end(endcode);
|
|
118
|
-
|
|
119
|
-
console.log('Total time ', process.hrtime(start));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (typeof process.argv[2] === 'string') { run(); }
|
|
123
|
-
else { console.error('Error: Please provide a file name.'); }
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/scratch/decode_aac.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Aerostat Beam Coder - Node.js native bindings for FFmpeg.
|
|
3
|
-
Copyright (C) 2019 Streampunk Media Ltd.
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify
|
|
6
|
-
it under the terms of the GNU General Public License as published by
|
|
7
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
(at your option) any later version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful,
|
|
11
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License
|
|
16
|
-
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
https://www.streampunk.media/ mailto:furnace@streampunk.media
|
|
19
|
-
14 Ormiscaig, Aultbea, Achnasheen, IV22 2JJ U.K.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
const beamcoder = require('../index.js');
|
|
23
|
-
|
|
24
|
-
async function run() {
|
|
25
|
-
let demuxer = await beamcoder.demuxer({ url: '../media/bbb_1080p_c.ts'});
|
|
26
|
-
let decoder = beamcoder.decoder({ name: 'aac' });
|
|
27
|
-
let packet = {};
|
|
28
|
-
for ( let x = 0 ; packet !== null && x < 100 ; x++ ) {
|
|
29
|
-
packet = await demuxer.read();
|
|
30
|
-
if (packet.stream_index == 1) {
|
|
31
|
-
console.log(JSON.stringify(packet, null, 2));
|
|
32
|
-
let frames = await decoder.decode(packet);
|
|
33
|
-
console.log(JSON.stringify(frames.frames[0], null, 2));
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
run();
|
package/scratch/decode_avci.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Aerostat Beam Coder - Node.js native bindings for FFmpeg.
|
|
3
|
-
Copyright (C) 2019 Streampunk Media Ltd.
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify
|
|
6
|
-
it under the terms of the GNU General Public License as published by
|
|
7
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
(at your option) any later version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful,
|
|
11
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License
|
|
16
|
-
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
https://www.streampunk.media/ mailto:furnace@streampunk.media
|
|
19
|
-
14 Ormiscaig, Aultbea, Achnasheen, IV22 2JJ U.K.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
const beamcoder = require('../index.js');
|
|
23
|
-
|
|
24
|
-
async function run() {
|
|
25
|
-
// let demuxer = await beamcoder.demuxer('../media/dpp/AS11_DPP_HD_EXAMPLE_1.mxf');
|
|
26
|
-
// console.log(JSON.stringify(demuxer, null, 2));
|
|
27
|
-
let demuxer = await beamcoder.demuxer('M:/dpp/AS11_4K_8.mxf');
|
|
28
|
-
// let demuxer = await beamcoder.demuxer('M:/dpp/AS11.mxf');
|
|
29
|
-
demuxer.streams.forEach(s => s.discard = (0 == s.index) ? 'default' : 'all');
|
|
30
|
-
// let decoder = beamcoder.decoder({ name: 'h264', thread_count: 4, thread_type: { FRAME: false, SLICE: true } });
|
|
31
|
-
let decoder = beamcoder.decoder({ name: 'h264', thread_count: 1, hwaccel: true });
|
|
32
|
-
// console.dir(decoder, { getters: true, depth: 3 });
|
|
33
|
-
let packet = {};
|
|
34
|
-
for ( let x = 0 ; x < 2000 && packet != null; x++ ) {
|
|
35
|
-
packet = await demuxer.read();
|
|
36
|
-
if (packet && packet.stream_index === 0) {
|
|
37
|
-
//console.log(JSON.stringify(packet, null, 2));
|
|
38
|
-
let frames = await decoder.decode(packet);
|
|
39
|
-
// console.log(JSON.stringify(frames.frames[0], null, 2));
|
|
40
|
-
if (frames.frames[0]) {
|
|
41
|
-
console.log(frames.frames[0].data);
|
|
42
|
-
}
|
|
43
|
-
console.log(x, frames.total_time);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
let frames = await decoder.flush();
|
|
47
|
-
console.log('flush', frames.total_time, frames.length);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
run();
|