bare-ffmpeg 1.0.0-23 → 1.0.0-25

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/README.md CHANGED
@@ -10,19 +10,59 @@ npm i bare-ffmpeg
10
10
 
11
11
  ### `IOContext`
12
12
 
13
- The `IOContext` API provides functionality to create input/output contexts for media files.
13
+ The `IOContext` API provides functionality to create input/output contexts for media files with support for streaming and custom I/O operations.
14
14
 
15
15
  ```js
16
- const io = new ffmpeg.IOContext(buffer)
16
+ const io = new ffmpeg.IOContext(buffer[, options])
17
17
  ```
18
18
 
19
19
  Parameters:
20
20
 
21
- - `buffer` (`Buffer`): The media data buffer
21
+ - `buffer` (`Buffer` | `number`): The media data buffer or buffer size for streaming
22
+ - `options` (`object`, optional): Configuration options
23
+ - `onread` (`function`): A function for refilling the buffer.
24
+ - `onwrite` (`function`): A function for writing the buffer contents.
25
+ - `onseek` (`function`): A function for seeking to specified byte position.
22
26
 
23
27
  **Returns**: A new `IOContext` instance
24
28
 
25
- Example:
29
+ #### Constructor Options
30
+
31
+ ##### `onread(buffer, requestedLen)`
32
+
33
+ Callback function called when FFmpeg needs to read data. For streaming scenarios where data is not available in a single buffer.
34
+
35
+ Parameters:
36
+
37
+ - `buffer` (`Buffer`): Buffer to fill with data
38
+ - `requestedLen` (`number`): Number of bytes requested
39
+
40
+ **Returns**: `number` - Number of bytes actually read, or 0 for EOF
41
+
42
+ ##### `onwrite(buffer)`
43
+
44
+ Callback function called when FFmpeg needs to write data. For streaming output scenarios.
45
+
46
+ Parameters:
47
+
48
+ - `buffer` (`Buffer`): Buffer containing data to write
49
+
50
+ **Returns**: `number` - Number of bytes written
51
+
52
+ ##### `onseek(offset, whence)`
53
+
54
+ Callback function called when FFmpeg needs to seek within the data source.
55
+
56
+ Parameters:
57
+
58
+ - `offset` (`number`): Offset to seek to
59
+ - `whence` (`number`): Seek mode (see `ffmpeg.constants.seek`)
60
+
61
+ **Returns**: `number` - New position or file size for `AVSEEK_SIZE`
62
+
63
+ #### Examples
64
+
65
+ **Basic usage with buffer:**
26
66
 
27
67
  ```js
28
68
  const image = require('./fixtures/image/sample.jpeg', {
@@ -32,6 +72,43 @@ const io = new ffmpeg.IOContext(image)
32
72
  io.destroy()
33
73
  ```
34
74
 
75
+ **Streaming with custom read callback:**
76
+
77
+ ```js
78
+ const io = new ffmpeg.IOContext(4096, {
79
+ onread: (buffer) => {
80
+ const bytesToRead = Math.min(buffer.length, data.length - offset)
81
+ if (bytesToRead === 0) return 0
82
+
83
+ const chunk = data.subarray(offset, offset + bytesToRead)
84
+ buffer.set(chunk)
85
+ offset += bytesToRead
86
+ return bytesToRead
87
+ }
88
+ })
89
+ ```
90
+
91
+ **Streaming with seek support:**
92
+
93
+ ```js
94
+ const io = new ffmpeg.IOContext(4096, {
95
+ onread: (buffer) => {
96
+ // ... read implementation
97
+ },
98
+ onseek: (offset, whence) => {
99
+ switch (whence) {
100
+ case ffmpeg.constants.seek.SIZE:
101
+ return data.length
102
+ case ffmpeg.constants.seek.SET:
103
+ offset = offset
104
+ return offset
105
+ default:
106
+ return -1
107
+ }
108
+ }
109
+ })
110
+ ```
111
+
35
112
  #### Methods
36
113
 
37
114
  ##### `IOContext.destroy()`
package/binding.cc CHANGED
@@ -33,9 +33,9 @@ extern "C" {
33
33
  #include <libswscale/swscale.h>
34
34
  }
35
35
 
36
- using bare_ffmpeg_io_context_write_cb_t = js_function_t<void, js_typedarray_t<uint8_t>>;
37
- using bare_ffmpeg_io_context_read_cb_t = js_function_t<int32_t, js_typedarray_t<uint8_t>, int32_t>;
38
- using bare_ffmpeg_io_context_seek_cb_t = js_function_t<int64_t, int64_t, std::string>;
36
+ using bare_ffmpeg_io_context_write_cb_t = js_function_t<void, js_arraybuffer_t>;
37
+ using bare_ffmpeg_io_context_read_cb_t = js_function_t<int32_t, js_arraybuffer_t, int32_t>;
38
+ using bare_ffmpeg_io_context_seek_cb_t = js_function_t<int64_t, int64_t, int>;
39
39
 
40
40
  typedef struct {
41
41
  AVIOContext *handle;
@@ -144,13 +144,9 @@ bare_ffmpeg__on_io_context_write(void *opaque, const uint8_t *buf, int len) {
144
144
  err = js_create_arraybuffer(env, buf, static_cast<size_t>(len), data);
145
145
  assert(err == 0);
146
146
 
147
- js_typedarray_t<uint8_t> view;
148
- err = js_create_typedarray(env, static_cast<size_t>(len), data, view);
149
- assert(err == 0);
150
-
147
+ err = js_call_function(env, callback, data);
151
148
 
152
- err = js_call_function(env, callback, view);
153
- assert(err == 0);
149
+ if (err < 0) return AVERROR(EIO);
154
150
 
155
151
  return 0;
156
152
  }
@@ -171,12 +167,8 @@ bare_ffmpeg__on_io_context_read(void *opaque, uint8_t *buf, int len) {
171
167
  err = js_create_external_arraybuffer(env, buf, static_cast<size_t>(len), arraybuffer);
172
168
  assert(err == 0);
173
169
 
174
- js_typedarray_t<uint8_t> view;
175
- err = js_create_typedarray(env, static_cast<size_t>(len), arraybuffer, view);
176
- assert(err == 0);
177
-
178
170
  int32_t result;
179
- int call_status = js_call_function<js_type_options_t{}, int32_t, js_typedarray_t<uint8_t>, int32_t>(env, callback, view, len, result);
171
+ int call_status = js_call_function<js_type_options_t{}, int32_t, js_arraybuffer_t, int32_t>(env, callback, arraybuffer, len, result);
180
172
 
181
173
  err = js_detach_arraybuffer(env, arraybuffer);
182
174
  assert(err == 0);
@@ -190,39 +182,21 @@ bare_ffmpeg__on_io_context_read(void *opaque, uint8_t *buf, int len) {
190
182
 
191
183
  static int64_t
192
184
  bare_ffmpeg__on_io_context_seek(void *opaque, int64_t offset, int whence) {
193
- int err;
194
-
195
185
  auto context = reinterpret_cast<bare_ffmpeg_io_context_t *>(opaque);
196
-
197
186
  auto env = context->env;
198
187
 
199
188
  int64_t result;
200
- std::string whence_str;
201
- switch (whence) {
202
- case AVSEEK_SIZE:
203
- whence_str = "avseek_size";
204
- break;
205
- case AVSEEK_FORCE:
206
- whence_str = "avseek_force";
207
- break;
208
- case SEEK_SET:
209
- whence_str = "seek_set";
210
- break;
211
- case SEEK_CUR:
212
- whence_str = "seek_cur";
213
- break;
214
- case SEEK_END:
215
- whence_str = "seek_end";
216
- break;
217
- default:
218
- whence_str = "unknown:" + std::to_string(whence);
219
- }
220
-
221
189
  bare_ffmpeg_io_context_seek_cb_t callback;
222
- err = js_get_reference_value(env, context->on_seek, callback);
190
+ int err = js_get_reference_value(env, context->on_seek, callback);
223
191
  assert(err == 0);
224
192
 
225
- err = js_call_function<js_type_options_t{}, int64_t, int64_t, std::string>(env, callback, offset, whence_str, result);
193
+ err = js_call_function<
194
+ js_type_options_t{},
195
+ int64_t,
196
+ int64_t,
197
+ int>(
198
+ env, callback, offset, whence, result
199
+ );
226
200
  if (err < 0) return AVERROR(EIO); // read-error
227
201
 
228
202
  if (result == -1) {
@@ -400,6 +374,12 @@ bare_ffmpeg_format_context_open_input_with_io(
400
374
  if (err < 0) {
401
375
  avformat_free_context(context->handle);
402
376
 
377
+ bool is_exception_pending;
378
+ err = js_is_exception_pending(env, &is_exception_pending);
379
+ assert(err == 0);
380
+
381
+ if (is_exception_pending) throw js_pending_exception;
382
+
403
383
  err = js_throw_error(env, NULL, av_err2str(err));
404
384
  assert(err == 0);
405
385
 
@@ -3430,6 +3410,13 @@ bare_ffmpeg_exports(js_env_t *env, js_value_t *exports) {
3430
3410
 
3431
3411
  // Levels
3432
3412
  V(AV_LEVEL_UNKNOWN)
3413
+
3414
+ // SEEK
3415
+ V(AVSEEK_SIZE)
3416
+ V(AVSEEK_FORCE)
3417
+ V(SEEK_CUR)
3418
+ V(SEEK_SET)
3419
+ V(SEEK_END)
3433
3420
  #undef V
3434
3421
 
3435
3422
  return exports;
@@ -332,7 +332,7 @@ list(APPEND env
332
332
  )
333
333
 
334
334
  declare_port(
335
- "github:FFmpeg/FFmpeg#n7.1.1"
335
+ "github:FFmpeg/FFmpeg#n8.0"
336
336
  ffmpeg
337
337
  AUTOTOOLS
338
338
  DEPENDS ${depends}
package/lib/constants.js CHANGED
@@ -133,6 +133,13 @@ module.exports = exports = {
133
133
  NOFILE: binding.AVFMT_NOFILE,
134
134
  NEEDNUMBER: binding.AVFMT_NEEDNUMBER,
135
135
  NOTIMESTAMPS: binding.AVFMT_NOTIMESTAMPS
136
+ },
137
+ seek: {
138
+ SIZE: binding.AVSEEK_SIZE,
139
+ FORCE: binding.AVSEEK_FORCE,
140
+ CUR: binding.SEEK_CUR,
141
+ SET: binding.SEEK_SET,
142
+ END: binding.SEEK_END
136
143
  }
137
144
  }
138
145
 
package/lib/io-context.js CHANGED
@@ -20,8 +20,8 @@ module.exports = class FFmpegIOContext {
20
20
  buffer,
21
21
  offset,
22
22
  len,
23
- opts.onwrite,
24
- opts.onread,
23
+ opts.onwrite && onwriteWrapper.bind(null, opts.onwrite),
24
+ opts.onread && onreadWrapper.bind(null, opts.onread),
25
25
  opts.onseek
26
26
  )
27
27
  }
@@ -35,3 +35,11 @@ module.exports = class FFmpegIOContext {
35
35
  this.destroy()
36
36
  }
37
37
  }
38
+
39
+ function onwriteWrapper(target, arraybuffer) {
40
+ return target(Buffer.from(arraybuffer))
41
+ }
42
+
43
+ function onreadWrapper(target, arraybuffer, requestedLen) {
44
+ return target(Buffer.from(arraybuffer), requestedLen)
45
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-ffmpeg",
3
- "version": "1.0.0-23",
3
+ "version": "1.0.0-25",
4
4
  "description": "Low-level FFmpeg bindings for Bare",
5
5
  "exports": {
6
6
  ".": "./index.js",