@lumen5/beamcoder 0.0.2 → 0.0.4

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.
@@ -4,8 +4,6 @@
4
4
  name: Node.js Package
5
5
 
6
6
  on:
7
- push:
8
- branches: [ "add-ci" ]
9
7
  release:
10
8
  types: [created]
11
9
 
@@ -23,6 +21,7 @@ jobs:
23
21
  registry-url: https://registry.npmjs.org/
24
22
  - run: mkdir /tmp/beamcoder
25
23
  - run: cp -r . /tmp/beamcoder
24
+ - run: sudo apt-get update && sudo apt-get install -y libvpx-dev
26
25
  - run: sudo ./scripts/install_beamcoder_dependencies.sh
27
26
  working-directory: /tmp/beamcoder
28
27
  - run: yarn install --frozen-lockfile
package/binding.gyp CHANGED
@@ -9,6 +9,9 @@
9
9
  "src/packet.cc", "src/frame.cc",
10
10
  "src/codec_par.cc", "src/format.cc",
11
11
  "src/codec.cc", "src/hwcontext.cc"],
12
+ "variables": {
13
+ "ffmpeg_static%": "<!(echo ${FFMPEG_STATIC:-1})"
14
+ },
12
15
  "conditions": [
13
16
  ['OS!="win"', {
14
17
  "defines": [
@@ -20,10 +23,12 @@
20
23
  ],
21
24
  "cflags_cc": [
22
25
  "-std=c++11",
23
- "-fexceptions"
26
+ "-fexceptions",
27
+ "-fPIC",
28
+ "-fvisibility=hidden"
24
29
  ]
25
30
  }],
26
- ['OS!="win" and OS!="linux"', {
31
+ ['OS!="win" and OS!="linux" and ffmpeg_static==0', {
27
32
  "link_settings": {
28
33
  "libraries": [
29
34
  "-lavcodec",
@@ -76,7 +81,61 @@
76
81
  }
77
82
  ]
78
83
  }],
79
- ['OS=="linux"', {
84
+ ['OS=="mac" and ffmpeg_static==0', {
85
+ "include_dirs" : [
86
+ "/usr/local/Cellar/ffmpeg@5/5.1.3/include/",
87
+ "/opt/homebrew/Cellar/ffmpeg@5/5.1.3/include/",
88
+ "/opt/homebrew/Cellar/ffmpeg@5/5.1.4_4/include/",
89
+ ],
90
+ "library_dirs": [
91
+ "/usr/local/Cellar/ffmpeg@5/5.1.3/lib/",
92
+ "/opt/homebrew/Cellar/ffmpeg@5/5.1.3/lib/",
93
+ "/opt/homebrew/Cellar/ffmpeg@5/5.1.4_4/lib/",
94
+ ]
95
+ }],
96
+ ['OS=="mac" and ffmpeg_static==1', {
97
+ "include_dirs": [
98
+ "ffmpeg/ffmpeg-static-build/include"
99
+ ],
100
+ "library_dirs": [
101
+ "/opt/homebrew/lib",
102
+ "/usr/local/lib"
103
+ ],
104
+ "libraries": [
105
+ "../ffmpeg/ffmpeg-static-build/lib/libavcodec.a",
106
+ "../ffmpeg/ffmpeg-static-build/lib/libavdevice.a",
107
+ "../ffmpeg/ffmpeg-static-build/lib/libavfilter.a",
108
+ "../ffmpeg/ffmpeg-static-build/lib/libavformat.a",
109
+ "../ffmpeg/ffmpeg-static-build/lib/libavutil.a",
110
+ "../ffmpeg/ffmpeg-static-build/lib/libpostproc.a",
111
+ "../ffmpeg/ffmpeg-static-build/lib/libswresample.a",
112
+ "../ffmpeg/ffmpeg-static-build/lib/libswscale.a",
113
+ "-framework VideoToolbox",
114
+ "-framework CoreMedia",
115
+ "-framework CoreVideo",
116
+ "-framework CoreFoundation",
117
+ "-framework Security",
118
+ "-framework AudioToolbox",
119
+ "-lvpx",
120
+ "-lbz2",
121
+ "-lz",
122
+ "-liconv",
123
+ "-lm"
124
+ ],
125
+ "xcode_settings": {
126
+ "OTHER_LDFLAGS": [
127
+ "-framework VideoToolbox",
128
+ "-framework CoreMedia",
129
+ "-framework CoreVideo",
130
+ "-framework CoreFoundation",
131
+ "-framework Security",
132
+ "-framework AudioToolbox",
133
+ "-exported_symbols_list",
134
+ "<(module_root_dir)/exports.txt"
135
+ ]
136
+ }
137
+ }],
138
+ ['OS=="linux" and ffmpeg_static==0', {
80
139
  "libraries": [
81
140
  "<!(pkg-config --libs libavcodec)",
82
141
  "<!(pkg-config --libs libavdevice)",
@@ -88,16 +147,27 @@
88
147
  "<!(pkg-config --libs libswscale)"
89
148
  ]
90
149
  }],
91
- ['OS=="mac"', {
92
- "include_dirs" : [
93
- "/usr/local/Cellar/ffmpeg@5/5.1.3/include/",
94
- "/opt/homebrew/Cellar/ffmpeg@5/5.1.3/include/",
95
- "/opt/homebrew/Cellar/ffmpeg@5/5.1.4_4/include/",
150
+ ['OS=="linux" and ffmpeg_static==1', {
151
+ "include_dirs": [
152
+ "ffmpeg/ffmpeg-static-build/include"
96
153
  ],
97
- "library_dirs": [
98
- "/usr/local/Cellar/ffmpeg@5/5.1.3/lib/",
99
- "/opt/homebrew/Cellar/ffmpeg@5/5.1.3/lib/",
100
- "/opt/homebrew/Cellar/ffmpeg@5/5.1.4_4/lib/",
154
+ "libraries": [
155
+ "../ffmpeg/ffmpeg-static-build/lib/libavcodec.a",
156
+ "../ffmpeg/ffmpeg-static-build/lib/libavdevice.a",
157
+ "../ffmpeg/ffmpeg-static-build/lib/libavfilter.a",
158
+ "../ffmpeg/ffmpeg-static-build/lib/libavformat.a",
159
+ "../ffmpeg/ffmpeg-static-build/lib/libavutil.a",
160
+ "../ffmpeg/ffmpeg-static-build/lib/libpostproc.a",
161
+ "../ffmpeg/ffmpeg-static-build/lib/libswresample.a",
162
+ "../ffmpeg/ffmpeg-static-build/lib/libswscale.a",
163
+ "-lvpx",
164
+ "-lz",
165
+ "-lm",
166
+ "-lpthread",
167
+ "-ldl"
168
+ ],
169
+ "ldflags": [
170
+ "-Wl,--version-script=<(module_root_dir)/exports.map"
101
171
  ]
102
172
  }],
103
173
  ]
package/exports.map ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ global:
3
+ napi_register_module_v1;
4
+ local:
5
+ *;
6
+ };
package/exports.txt ADDED
@@ -0,0 +1 @@
1
+ _napi_register_module_v1
package/index.js CHANGED
@@ -22,10 +22,6 @@
22
22
  const beamcoder = require('bindings')('beamcoder');
23
23
  const beamstreams = require('./beamstreams.js');
24
24
 
25
- // Provide useful debug on segfault-related crash
26
- const SegfaultHandler = require('segfault-handler');
27
- SegfaultHandler.registerHandler('crash.log');
28
-
29
25
  const splash = `Aerostat Beam Coder Copyright (C) 2019 Streampunk Media Ltd
30
26
  GPL v3.0 or later license. This program comes with ABSOLUTELY NO WARRANTY.
31
27
  This is free software, and you are welcome to redistribute it
@@ -0,0 +1,285 @@
1
+ /*
2
+ Aerostat Beam Coder - Node.js native bindings to 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 os = require('os');
23
+ const fs = require('fs');
24
+ const util = require('util');
25
+ const https = require('https');
26
+ const cp = require('child_process');
27
+ const path = require('path');
28
+ const [ mkdir, access, rename, execFile, exec ] = // eslint-disable-line
29
+ [ fs.mkdir, fs.access, fs.rename, cp.execFile, cp.exec ].map(util.promisify);
30
+
31
+ // GitHub repository with pre-built static libraries
32
+ const GITHUB_REPO = 'Lumen5/ffmpeg-static';
33
+ const GITHUB_BRANCH = 'main';
34
+
35
+ // Get platform string for static library directory
36
+ // Maps to the directory structure in ffmpeg-static: output/linux/{amd64,arm64}, output/darwin/arm64
37
+ function getPlatform() {
38
+ const platform = os.platform();
39
+ const arch = os.arch();
40
+
41
+ // Map Node.js arch to platform format
42
+ // Note: macOS arm64 uses linux/arm64 binaries
43
+ if (arch === 'x64') {
44
+ if (platform !== 'linux') {
45
+ throw new Error(`Platform ${platform} with x64 architecture is not supported for static linking. Only Linux x64 is supported.`);
46
+ }
47
+ return 'linux/amd64';
48
+ } else if (arch === 'arm64') {
49
+ if (platform === 'linux') {
50
+ return 'linux/arm64';
51
+ } else if (platform === 'darwin') {
52
+ return 'darwin/arm64';
53
+ } else {
54
+ throw new Error(`Platform ${platform} with arm64 architecture is not supported for static linking.`);
55
+ }
56
+ } else {
57
+ throw new Error(`Architecture ${arch} is not supported. Only x64 (amd64) and arm64 are supported.`);
58
+ }
59
+ }
60
+
61
+ // Get the download URL for the repository archive
62
+ function getDownloadUrl() {
63
+ return `https://github.com/${GITHUB_REPO}/archive/refs/heads/${GITHUB_BRANCH}.tar.gz`;
64
+ }
65
+
66
+ async function download(url, destPath, name) {
67
+ return new Promise((resolve, reject) => {
68
+ console.log(`Downloading ${name} from ${url}...`);
69
+ const file = fs.createWriteStream(destPath);
70
+ let received = 0;
71
+ let totalLength = 0;
72
+
73
+ https.get(url, res => {
74
+ if (res.statusCode === 301 || res.statusCode === 302) {
75
+ file.close();
76
+ fs.unlinkSync(destPath);
77
+ // Follow redirect
78
+ return download(res.headers.location, destPath, name).then(resolve).catch(reject);
79
+ }
80
+
81
+ totalLength = +res.headers['content-length'] || 0;
82
+ res.pipe(file);
83
+
84
+ res.on('data', chunk => {
85
+ received += chunk.length;
86
+ if (totalLength > 0) {
87
+ process.stdout.write(`Downloaded ${Math.floor(received * 100 / totalLength)}% of '${name}'.\r`);
88
+ }
89
+ });
90
+
91
+ file.on('finish', () => {
92
+ file.close();
93
+ console.log(`\nDownloaded 100% of '${name}'. Total length ${received} bytes.`);
94
+ resolve();
95
+ });
96
+ }).on('error', err => {
97
+ fs.unlinkSync(destPath);
98
+ reject(err);
99
+ });
100
+
101
+ file.on('error', err => {
102
+ fs.unlinkSync(destPath);
103
+ reject(err);
104
+ });
105
+ });
106
+ }
107
+
108
+ async function extractTarGz(tarPath, destDir) {
109
+ console.log(`Extracting ${tarPath} to ${destDir}...`);
110
+ await exec(`tar -xzf ${tarPath} -C ${destDir}`);
111
+ console.log('Extraction complete.');
112
+ }
113
+
114
+ async function downloadFFmpegStatic() {
115
+ const ffmpegDir = path.join(__dirname, 'ffmpeg');
116
+ const buildDir = path.join(ffmpegDir, 'ffmpeg-static-build');
117
+ const tarPath = path.join(ffmpegDir, 'ffmpeg-static.tar.gz');
118
+ const extractDir = path.join(ffmpegDir, 'ffmpeg-static-main');
119
+
120
+ // Clean up previous installation
121
+ if (fs.existsSync(ffmpegDir)) {
122
+ console.log('Removing previous installation...');
123
+ await exec(`rm -rf ${ffmpegDir}`);
124
+ }
125
+
126
+ // Create ffmpeg directory
127
+ await mkdir(ffmpegDir).catch(e => {
128
+ if (e.code === 'EEXIST') return;
129
+ else throw e;
130
+ });
131
+
132
+ // Check if already downloaded - verify all required libraries exist
133
+ // Note: Based on https://github.com/Lumen5/ffmpeg-static repo structure
134
+ const requiredLibs = [
135
+ 'libavcodec.a',
136
+ 'libavdevice.a',
137
+ 'libavfilter.a',
138
+ 'libavformat.a',
139
+ 'libavutil.a',
140
+ 'libpostproc.a',
141
+ 'libswresample.a',
142
+ 'libswscale.a'
143
+ ];
144
+
145
+ // No optional libraries
146
+ const optionalLibs = [];
147
+
148
+ try {
149
+ // Check all libraries exist
150
+ for (const lib of requiredLibs) {
151
+ await access(path.join(buildDir, 'lib', lib), fs.constants.R_OK);
152
+ }
153
+ console.log('FFmpeg static libraries already present.');
154
+ return buildDir;
155
+ } catch (err) {
156
+ console.log('Downloading FFmpeg static libraries from GitHub...');
157
+ // Clean up incomplete build directory if it exists
158
+ if (fs.existsSync(buildDir)) {
159
+ console.log('Removing incomplete installation...');
160
+ await exec(`rm -rf ${buildDir}`);
161
+ }
162
+ }
163
+
164
+ // Get download URL
165
+ const downloadUrl = getDownloadUrl();
166
+ console.log(`Downloading from: https://github.com/${GITHUB_REPO}`);
167
+
168
+ // Download pre-built binaries from GitHub
169
+ try {
170
+ await download(downloadUrl, tarPath, 'ffmpeg-static repository');
171
+ } catch (err) {
172
+ console.error(`Failed to download FFmpeg static binaries from ${downloadUrl}`);
173
+ console.error(`Please ensure https://github.com/${GITHUB_REPO} is accessible.`);
174
+ throw err;
175
+ }
176
+
177
+ // Extract the archive
178
+ console.log('Extracting FFmpeg static libraries...');
179
+ await extractTarGz(tarPath, ffmpegDir);
180
+
181
+ // Get the platform-specific directory
182
+ const platformDir = getPlatform();
183
+ console.log(`Using platform: ${platformDir}`);
184
+
185
+ // Copy output directory contents to ffmpeg-static-build
186
+ // The repo has structure: ffmpeg-static-main/output/{linux/{amd64,arm64},darwin/arm64}/{lib,include}
187
+ // We need: ffmpeg-static-build/{lib,include}
188
+ console.log('Setting up library directories...');
189
+
190
+ const outputDir = path.join(extractDir, 'output', platformDir);
191
+ if (!fs.existsSync(outputDir)) {
192
+ throw new Error(`Expected directory not found: ${outputDir}. Platform ${platformDir} may not be available in the repository.`);
193
+ }
194
+
195
+ // Create build directory
196
+ await mkdir(buildDir).catch(e => {
197
+ if (e.code === 'EEXIST') return;
198
+ else throw e;
199
+ });
200
+
201
+ // Copy contents of platform-specific output directory (lib and include) to ffmpeg-static-build
202
+ await exec(`cp -r "${outputDir}"/* "${buildDir}"/`);
203
+
204
+ // Verify all required libraries were copied
205
+ try {
206
+ for (const lib of requiredLibs) {
207
+ await access(path.join(buildDir, 'lib', lib), fs.constants.R_OK);
208
+ }
209
+ console.log('FFmpeg static libraries installed successfully.');
210
+
211
+ // Check for optional libraries
212
+ for (const lib of optionalLibs) {
213
+ try {
214
+ await access(path.join(buildDir, 'lib', lib), fs.constants.R_OK);
215
+ console.log(` Optional library found: ${lib}`);
216
+ } catch (err) {
217
+ console.log(` Optional library not found: ${lib} (skipping)`);
218
+ }
219
+ }
220
+ } catch (err) {
221
+ console.error('Installation failed: Not all required libraries were found.');
222
+ console.error(`Expected libraries in: ${buildDir}/lib/`);
223
+ throw err;
224
+ }
225
+
226
+ // Clean up temporary files
227
+ console.log('Cleaning up...');
228
+ if (fs.existsSync(tarPath)) {
229
+ await exec(`rm ${tarPath}`);
230
+ }
231
+ if (fs.existsSync(extractDir)) {
232
+ await exec(`rm -rf ${extractDir}`);
233
+ }
234
+
235
+ return buildDir;
236
+ }
237
+
238
+ async function win32() {
239
+ console.log('Building static FFmpeg libraries on Windows is complex.');
240
+ console.log('For Windows, consider using pre-built static libraries or use WSL/MSYS2.');
241
+ console.log('This script focuses on Linux and macOS support.');
242
+ process.exit(1);
243
+ }
244
+
245
+ async function linux() {
246
+ const platformDir = getPlatform();
247
+ console.log(`Installing FFmpeg static libraries for Linux (${platformDir}).`);
248
+ await downloadFFmpegStatic();
249
+ }
250
+
251
+ async function darwin() {
252
+ const platformDir = getPlatform();
253
+ console.log(`Installing FFmpeg static libraries for macOS (${platformDir}).`);
254
+ await downloadFFmpegStatic();
255
+ }
256
+
257
+ switch (os.platform()) {
258
+ case 'win32':
259
+ if (os.arch() != 'x64') {
260
+ console.error('Only 64-bit platforms are supported.');
261
+ process.exit(1);
262
+ } else {
263
+ win32().catch(console.error);
264
+ }
265
+ break;
266
+ case 'linux':
267
+ if (os.arch() != 'x64' && os.arch() != 'arm64') {
268
+ console.error('Only 64-bit platforms are supported.');
269
+ process.exit(1);
270
+ } else {
271
+ linux().catch(console.error);
272
+ }
273
+ break;
274
+ case 'darwin':
275
+ if (os.arch() != 'x64' && os.arch() != 'arm64') {
276
+ console.error('Only 64-bit platforms are supported.');
277
+ process.exit(1);
278
+ } else {
279
+ darwin().catch(console.error);
280
+ }
281
+ break;
282
+ default:
283
+ console.error(`Platform ${os.platform()} is not supported.`);
284
+ break;
285
+ }
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@lumen5/beamcoder",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Node.js native bindings to FFmpeg.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "scripts": {
8
- "preinstall": "node install_ffmpeg.js",
9
- "install": "node-gyp rebuild",
8
+ "preinstall": "node install_ffmpeg_static.js",
9
+ "install": "FFMPEG_STATIC=1 node-gyp rebuild",
10
+ "preinstall:dynamic": "node install_ffmpeg.js",
11
+ "install:dynamic": "FFMPEG_STATIC=0 node-gyp rebuild",
12
+ "build:dynamic": "npm run preinstall:dynamic && npm run install:dynamic",
10
13
  "test": "tape test/*.js",
11
14
  "lint": "eslint **/*.js",
12
15
  "lint-html": "eslint **/*.js -f html -o ./reports/lint-results.html",
@@ -34,8 +37,7 @@
34
37
  },
35
38
  "homepage": "https://github.com/Streampunk/beamcoder#readme",
36
39
  "dependencies": {
37
- "bindings": "^1.5.0",
38
- "segfault-handler": "^1.3.0"
40
+ "bindings": "^1.5.0"
39
41
  },
40
42
  "devDependencies": {
41
43
  "eslint": "^8.9.0",