bare-media 1.2.0 → 1.3.0

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
@@ -29,15 +29,14 @@ const data = await worker.createPreview({ path, maxWidth, maxHeight })
29
29
 
30
30
  > NOTE: A worker spawns when an operation is requested and it stays running until the parent process is killed.
31
31
 
32
- Handle close event:
32
+ Terminate the worker:
33
33
 
34
34
  ```js
35
- import worker from 'bare-media'
35
+ worker.close()
36
36
 
37
37
  worker.onClose = () => {
38
- // worker closed unexpectedly
38
+ // worker terminated
39
39
  }
40
-
41
40
  ```
42
41
 
43
42
  Call the methods directly without a worker:
@@ -50,10 +49,10 @@ const data = await createPreview({ path, maxWidth, maxHeight })
50
49
 
51
50
  ## API
52
51
 
53
- | Method | Parameters | Return Value | Description
54
- |---------------------|---------------------------------------------------------|---------------------|----------------------------------------
55
- | `createPreview` | `path, mimetype, maxWidth, maxHeight, format, encoding` | `metadata, preview` | Create a preview from a media file
56
- | `decodeImage` | `path`, `httpLink, mimetype` | `metadata, data` | Decode an image to RGBA
52
+ | Method | Parameters | Return Value | Description |
53
+ | --------------- | ------------------------------------------------------- | ------------------- | ---------------------------------- |
54
+ | `createPreview` | `path, mimetype, maxWidth, maxHeight, format, encoding` | `metadata, preview` | Create a preview from a media file |
55
+ | `decodeImage` | `path`, `httpLink, mimetype` | `metadata, data` | Decode an image to RGBA |
57
56
 
58
57
  > See [schema.js](shared/spec/schema.js) for the complete reference of parameters
59
58
 
package/client.js CHANGED
@@ -9,21 +9,22 @@ export class WorkerClient extends ReadyResource {
9
9
  rpc = null
10
10
  opts = null
11
11
 
12
- constructor (opts) {
12
+ constructor(opts) {
13
13
  super()
14
14
  this.initialize(opts)
15
15
  this.#attachMethods()
16
16
  }
17
17
 
18
- initialize ({ filename = 'node_modules/bare-media/worker/index.js', requireSource, args } = {}) {
18
+ initialize({
19
+ filename = 'node_modules/bare-media/worker/index.js',
20
+ requireSource,
21
+ args
22
+ } = {}) {
19
23
  this.opts = { filename, requireSource, args }
20
24
  }
21
25
 
22
- #attachMethods () {
23
- const methods = [
24
- 'createPreview',
25
- 'decodeImage'
26
- ]
26
+ #attachMethods() {
27
+ const methods = ['createPreview', 'decodeImage']
27
28
 
28
29
  for (const method of methods) {
29
30
  this[method] = async (...args) => {
@@ -33,11 +34,15 @@ export class WorkerClient extends ReadyResource {
33
34
  }
34
35
  }
35
36
 
36
- async _open () {
37
+ async _open() {
37
38
  await this.#run()
38
39
  }
39
40
 
40
- async #run () {
41
+ async _close() {
42
+ this.worker?.IPC.end()
43
+ }
44
+
45
+ async #run() {
41
46
  const { filename, requireSource, args } = this.opts
42
47
  const source = requireSource?.()
43
48
  this.worker = await spawn(filename, source, args)
@@ -50,7 +55,7 @@ export class WorkerClient extends ReadyResource {
50
55
  this.rpc = new HRPC(ipc)
51
56
  }
52
57
 
53
- isCodecSupported (mimetype) {
58
+ isCodecSupported(mimetype) {
54
59
  return isCodecSupported(mimetype)
55
60
  }
56
61
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "bare-media",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "build:rpc": "cd shared/spec && bare ./build.js",
8
- "lint": "standard",
9
- "lint:fix": "standard --fix",
10
- "test": "npm run lint && brittle-bare test/index.js"
8
+ "format": "prettier --write .",
9
+ "format:check": "prettier --check .",
10
+ "test": "npm run format:check && brittle-bare test/index.js"
11
11
  },
12
12
  "keywords": [],
13
13
  "author": "Holepunch Inc",
@@ -35,7 +35,8 @@
35
35
  "corestore": "^7.4.5",
36
36
  "hyperblobs": "^2.8.0",
37
37
  "hypercore-blob-server": "^1.11.0",
38
- "standard": "^17.1.2",
38
+ "prettier": "^3.6.2",
39
+ "prettier-config-holepunch": "^1.0.0",
39
40
  "test-tmp": "^1.4.0"
40
41
  },
41
42
  "files": [
@@ -43,11 +44,5 @@
43
44
  "worker",
44
45
  "client.js",
45
46
  "index.js"
46
- ],
47
- "standard": {
48
- "globals": [
49
- "Bare",
50
- "Pear"
51
- ]
52
- }
47
+ ]
53
48
  }
package/shared/codecs.js CHANGED
@@ -10,11 +10,11 @@ export const codecs = {
10
10
  'image/tiff': () => import('bare-tiff')
11
11
  }
12
12
 
13
- export function isCodecSupported (mimetype) {
13
+ export function isCodecSupported(mimetype) {
14
14
  return mimetype in codecs
15
15
  }
16
16
 
17
- export async function importCodec (mimetype) {
17
+ export async function importCodec(mimetype) {
18
18
  const codecImport = codecs[mimetype]
19
19
  if (!codecImport) throw new Error(`No codec for ${mimetype}`)
20
20
  return await codecImport()
@@ -28,4 +28,4 @@
28
28
  "version": 1
29
29
  }
30
30
  ]
31
- }
31
+ }
@@ -12,7 +12,7 @@ const methods = new Map([
12
12
  ])
13
13
 
14
14
  class HRPC {
15
- constructor (stream) {
15
+ constructor(stream) {
16
16
  this._stream = stream
17
17
  this._handlers = []
18
18
  this._requestEncodings = new Map([
@@ -39,23 +39,40 @@ class HRPC {
39
39
  }
40
40
  if (!this._requestIsStream(command) && this._responseIsStream(command)) {
41
41
  const request = req.data ? c.decode(requestEncoding, req.data) : null
42
- const responseStream = new RPCStream(null, null, req.createResponseStream(), responseEncoding)
42
+ const responseStream = new RPCStream(
43
+ null,
44
+ null,
45
+ req.createResponseStream(),
46
+ responseEncoding
47
+ )
43
48
  responseStream.data = request
44
49
  await this._handlers[command](responseStream)
45
50
  }
46
51
  if (this._requestIsStream(command) && !this._responseIsStream(command)) {
47
- const requestStream = new RPCRequestStream(req, responseEncoding, req.createRequestStream(), requestEncoding)
52
+ const requestStream = new RPCRequestStream(
53
+ req,
54
+ responseEncoding,
55
+ req.createRequestStream(),
56
+ requestEncoding
57
+ )
48
58
  const response = await this._handlers[command](requestStream)
49
59
  req.reply(c.encode(responseEncoding, response))
50
60
  }
51
61
  if (this._requestIsStream(command) && this._responseIsStream(command)) {
52
- const requestStream = new RPCRequestStream(req, responseEncoding, req.createRequestStream(), requestEncoding, req.createResponseStream(), responseEncoding)
62
+ const requestStream = new RPCRequestStream(
63
+ req,
64
+ responseEncoding,
65
+ req.createRequestStream(),
66
+ requestEncoding,
67
+ req.createResponseStream(),
68
+ responseEncoding
69
+ )
53
70
  await this._handlers[command](requestStream)
54
71
  }
55
72
  })
56
73
  }
57
74
 
58
- async _call (name, args) {
75
+ async _call(name, args) {
59
76
  const requestEncoding = this._requestEncodings.get(name)
60
77
  const responseEncoding = this._responseEncodings.get(name)
61
78
  const request = this._rpc.request(methods.get(name))
@@ -64,7 +81,7 @@ class HRPC {
64
81
  return c.decode(responseEncoding, await request.reply())
65
82
  }
66
83
 
67
- _callSync (name, args) {
84
+ _callSync(name, args) {
68
85
  const requestEncoding = this._requestEncodings.get(name)
69
86
  const responseEncoding = this._responseEncodings.get(name)
70
87
  const request = this._rpc.request(methods.get(name))
@@ -78,42 +95,53 @@ class HRPC {
78
95
  return new RPCStream(request.createResponseStream(), responseEncoding)
79
96
  }
80
97
  if (this._requestIsStream(name) && !this._responseIsStream(name)) {
81
- return new RPCRequestStream(request, responseEncoding, null, null, request.createRequestStream(), requestEncoding)
98
+ return new RPCRequestStream(
99
+ request,
100
+ responseEncoding,
101
+ null,
102
+ null,
103
+ request.createRequestStream(),
104
+ requestEncoding
105
+ )
82
106
  }
83
107
  if (this._requestIsStream(name) && this._responseIsStream(name)) {
84
- return new RPCRequestStream(request, responseEncoding, request.createResponseStream(), responseEncoding, request.createRequestStream(), requestEncoding)
108
+ return new RPCRequestStream(
109
+ request,
110
+ responseEncoding,
111
+ request.createResponseStream(),
112
+ responseEncoding,
113
+ request.createRequestStream(),
114
+ requestEncoding
115
+ )
85
116
  }
86
117
  }
87
118
 
88
- async createPreview (args) {
119
+ async createPreview(args) {
89
120
  return this._call('@media/create-preview', args)
90
121
  }
91
122
 
92
- async decodeImage (args) {
123
+ async decodeImage(args) {
93
124
  return this._call('@media/decode-image', args)
94
125
  }
95
126
 
96
- onCreatePreview (responseFn) {
127
+ onCreatePreview(responseFn) {
97
128
  this._handlers['@media/create-preview'] = responseFn
98
129
  }
99
130
 
100
- onDecodeImage (responseFn) {
131
+ onDecodeImage(responseFn) {
101
132
  this._handlers['@media/decode-image'] = responseFn
102
133
  }
103
134
 
104
- _requestIsStream (command) {
105
- return [
106
- ].includes(command)
135
+ _requestIsStream(command) {
136
+ return [].includes(command)
107
137
  }
108
138
 
109
- _responseIsStream (command) {
110
- return [
111
- ].includes(command)
139
+ _responseIsStream(command) {
140
+ return [].includes(command)
112
141
  }
113
142
 
114
- _requestIsSend (command) {
115
- return [
116
- ].includes(command)
143
+ _requestIsSend(command) {
144
+ return [].includes(command)
117
145
  }
118
146
  }
119
147
 
@@ -12,15 +12,15 @@ let version = VERSION
12
12
 
13
13
  // @media/dimensions
14
14
  const encoding0 = {
15
- preencode (state, m) {
15
+ preencode(state, m) {
16
16
  c.uint.preencode(state, m.width)
17
17
  c.uint.preencode(state, m.height)
18
18
  },
19
- encode (state, m) {
19
+ encode(state, m) {
20
20
  c.uint.encode(state, m.width)
21
21
  c.uint.encode(state, m.height)
22
22
  },
23
- decode (state) {
23
+ decode(state) {
24
24
  const r0 = c.uint.decode(state)
25
25
  const r1 = c.uint.decode(state)
26
26
 
@@ -36,18 +36,16 @@ const encoding1_1 = c.frame(encoding0)
36
36
 
37
37
  // @media/metadata
38
38
  const encoding1 = {
39
- preencode (state, m) {
39
+ preencode(state, m) {
40
40
  state.end++ // max flag is 4 so always one byte
41
41
 
42
42
  if (m.mimetype) c.string.preencode(state, m.mimetype)
43
43
  if (m.dimensions) encoding1_1.preencode(state, m.dimensions)
44
44
  if (m.duration) c.uint.preencode(state, m.duration)
45
45
  },
46
- encode (state, m) {
46
+ encode(state, m) {
47
47
  const flags =
48
- (m.mimetype ? 1 : 0) |
49
- (m.dimensions ? 2 : 0) |
50
- (m.duration ? 4 : 0)
48
+ (m.mimetype ? 1 : 0) | (m.dimensions ? 2 : 0) | (m.duration ? 4 : 0)
51
49
 
52
50
  c.uint.encode(state, flags)
53
51
 
@@ -55,7 +53,7 @@ const encoding1 = {
55
53
  if (m.dimensions) encoding1_1.encode(state, m.dimensions)
56
54
  if (m.duration) c.uint.encode(state, m.duration)
57
55
  },
58
- decode (state) {
56
+ decode(state) {
59
57
  const flags = c.uint.decode(state)
60
58
 
61
59
  return {
@@ -71,18 +69,16 @@ const encoding2_0 = c.frame(encoding1)
71
69
 
72
70
  // @media/file
73
71
  const encoding2 = {
74
- preencode (state, m) {
72
+ preencode(state, m) {
75
73
  state.end++ // max flag is 4 so always one byte
76
74
 
77
75
  if (m.metadata) encoding2_0.preencode(state, m.metadata)
78
76
  if (m.inlined) c.string.preencode(state, m.inlined)
79
77
  if (m.buffer) c.buffer.preencode(state, m.buffer)
80
78
  },
81
- encode (state, m) {
79
+ encode(state, m) {
82
80
  const flags =
83
- (m.metadata ? 1 : 0) |
84
- (m.inlined ? 2 : 0) |
85
- (m.buffer ? 4 : 0)
81
+ (m.metadata ? 1 : 0) | (m.inlined ? 2 : 0) | (m.buffer ? 4 : 0)
86
82
 
87
83
  c.uint.encode(state, flags)
88
84
 
@@ -90,7 +86,7 @@ const encoding2 = {
90
86
  if (m.inlined) c.string.encode(state, m.inlined)
91
87
  if (m.buffer) c.buffer.encode(state, m.buffer)
92
88
  },
93
- decode (state) {
89
+ decode(state) {
94
90
  const flags = c.uint.decode(state)
95
91
 
96
92
  return {
@@ -103,7 +99,7 @@ const encoding2 = {
103
99
 
104
100
  // @media/create-preview-request
105
101
  const encoding3 = {
106
- preencode (state, m) {
102
+ preencode(state, m) {
107
103
  c.string.preencode(state, m.path)
108
104
  state.end++ // max flag is 16 so always one byte
109
105
 
@@ -113,7 +109,7 @@ const encoding3 = {
113
109
  if (m.format) c.string.preencode(state, m.format)
114
110
  if (m.encoding) c.string.preencode(state, m.encoding)
115
111
  },
116
- encode (state, m) {
112
+ encode(state, m) {
117
113
  const flags =
118
114
  (m.mimetype ? 1 : 0) |
119
115
  (m.maxWidth ? 2 : 0) |
@@ -130,7 +126,7 @@ const encoding3 = {
130
126
  if (m.format) c.string.encode(state, m.format)
131
127
  if (m.encoding) c.string.encode(state, m.encoding)
132
128
  },
133
- decode (state) {
129
+ decode(state) {
134
130
  const r0 = c.string.decode(state)
135
131
  const flags = c.uint.decode(state)
136
132
 
@@ -152,15 +148,15 @@ const encoding4_1 = c.frame(encoding2)
152
148
 
153
149
  // @media/create-preview-response
154
150
  const encoding4 = {
155
- preencode (state, m) {
151
+ preencode(state, m) {
156
152
  encoding4_0.preencode(state, m.metadata)
157
153
  encoding4_1.preencode(state, m.preview)
158
154
  },
159
- encode (state, m) {
155
+ encode(state, m) {
160
156
  encoding4_0.encode(state, m.metadata)
161
157
  encoding4_1.encode(state, m.preview)
162
158
  },
163
- decode (state) {
159
+ decode(state) {
164
160
  const r0 = encoding4_0.decode(state)
165
161
  const r1 = encoding4_1.decode(state)
166
162
 
@@ -173,18 +169,15 @@ const encoding4 = {
173
169
 
174
170
  // @media/decode-image-request
175
171
  const encoding5 = {
176
- preencode (state, m) {
172
+ preencode(state, m) {
177
173
  state.end++ // max flag is 4 so always one byte
178
174
 
179
175
  if (m.path) c.string.preencode(state, m.path)
180
176
  if (m.httpLink) c.string.preencode(state, m.httpLink)
181
177
  if (m.mimetype) c.string.preencode(state, m.mimetype)
182
178
  },
183
- encode (state, m) {
184
- const flags =
185
- (m.path ? 1 : 0) |
186
- (m.httpLink ? 2 : 0) |
187
- (m.mimetype ? 4 : 0)
179
+ encode(state, m) {
180
+ const flags = (m.path ? 1 : 0) | (m.httpLink ? 2 : 0) | (m.mimetype ? 4 : 0)
188
181
 
189
182
  c.uint.encode(state, flags)
190
183
 
@@ -192,7 +185,7 @@ const encoding5 = {
192
185
  if (m.httpLink) c.string.encode(state, m.httpLink)
193
186
  if (m.mimetype) c.string.encode(state, m.mimetype)
194
187
  },
195
- decode (state) {
188
+ decode(state) {
196
189
  const flags = c.uint.decode(state)
197
190
 
198
191
  return {
@@ -208,23 +201,21 @@ const encoding6_0 = encoding2_0
208
201
 
209
202
  // @media/decode-image-response
210
203
  const encoding6 = {
211
- preencode (state, m) {
204
+ preencode(state, m) {
212
205
  state.end++ // max flag is 2 so always one byte
213
206
 
214
207
  if (m.metadata) encoding6_0.preencode(state, m.metadata)
215
208
  if (m.data) c.buffer.preencode(state, m.data)
216
209
  },
217
- encode (state, m) {
218
- const flags =
219
- (m.metadata ? 1 : 0) |
220
- (m.data ? 2 : 0)
210
+ encode(state, m) {
211
+ const flags = (m.metadata ? 1 : 0) | (m.data ? 2 : 0)
221
212
 
222
213
  c.uint.encode(state, flags)
223
214
 
224
215
  if (m.metadata) encoding6_0.encode(state, m.metadata)
225
216
  if (m.data) c.buffer.encode(state, m.data)
226
217
  },
227
- decode (state) {
218
+ decode(state) {
228
219
  const flags = c.uint.decode(state)
229
220
 
230
221
  return {
@@ -234,51 +225,60 @@ const encoding6 = {
234
225
  }
235
226
  }
236
227
 
237
- function setVersion (v) {
228
+ function setVersion(v) {
238
229
  version = v
239
230
  }
240
231
 
241
- function encode (name, value, v = VERSION) {
232
+ function encode(name, value, v = VERSION) {
242
233
  version = v
243
234
  return c.encode(getEncoding(name), value)
244
235
  }
245
236
 
246
- function decode (name, buffer, v = VERSION) {
237
+ function decode(name, buffer, v = VERSION) {
247
238
  version = v
248
239
  return c.decode(getEncoding(name), buffer)
249
240
  }
250
241
 
251
- function getEnum (name) {
242
+ function getEnum(name) {
252
243
  switch (name) {
253
- default: throw new Error('Enum not found ' + name)
244
+ default:
245
+ throw new Error('Enum not found ' + name)
254
246
  }
255
247
  }
256
248
 
257
- function getEncoding (name) {
249
+ function getEncoding(name) {
258
250
  switch (name) {
259
- case '@media/dimensions': return encoding0
260
- case '@media/metadata': return encoding1
261
- case '@media/file': return encoding2
262
- case '@media/create-preview-request': return encoding3
263
- case '@media/create-preview-response': return encoding4
264
- case '@media/decode-image-request': return encoding5
265
- case '@media/decode-image-response': return encoding6
266
- default: throw new Error('Encoder not found ' + name)
251
+ case '@media/dimensions':
252
+ return encoding0
253
+ case '@media/metadata':
254
+ return encoding1
255
+ case '@media/file':
256
+ return encoding2
257
+ case '@media/create-preview-request':
258
+ return encoding3
259
+ case '@media/create-preview-response':
260
+ return encoding4
261
+ case '@media/decode-image-request':
262
+ return encoding5
263
+ case '@media/decode-image-response':
264
+ return encoding6
265
+ default:
266
+ throw new Error('Encoder not found ' + name)
267
267
  }
268
268
  }
269
269
 
270
- function getStruct (name, v = VERSION) {
270
+ function getStruct(name, v = VERSION) {
271
271
  const enc = getEncoding(name)
272
272
  return {
273
- preencode (state, m) {
273
+ preencode(state, m) {
274
274
  version = v
275
275
  enc.preencode(state, m)
276
276
  },
277
- encode (state, m) {
277
+ encode(state, m) {
278
278
  version = v
279
279
  enc.encode(state, m)
280
280
  },
281
- decode (state) {
281
+ decode(state) {
282
282
  version = v
283
283
  return enc.decode(state)
284
284
  }
@@ -287,4 +287,13 @@ function getStruct (name, v = VERSION) {
287
287
 
288
288
  const resolveStruct = getStruct // compat
289
289
 
290
- export { resolveStruct, getStruct, getEnum, getEncoding, encode, decode, setVersion, version }
290
+ export {
291
+ resolveStruct,
292
+ getStruct,
293
+ getEnum,
294
+ getEncoding,
295
+ encode,
296
+ decode,
297
+ setVersion,
298
+ version
299
+ }
@@ -12,15 +12,15 @@ let version = VERSION
12
12
 
13
13
  // @media/dimensions
14
14
  const encoding0 = {
15
- preencode (state, m) {
15
+ preencode(state, m) {
16
16
  c.uint.preencode(state, m.width)
17
17
  c.uint.preencode(state, m.height)
18
18
  },
19
- encode (state, m) {
19
+ encode(state, m) {
20
20
  c.uint.encode(state, m.width)
21
21
  c.uint.encode(state, m.height)
22
22
  },
23
- decode (state) {
23
+ decode(state) {
24
24
  const r0 = c.uint.decode(state)
25
25
  const r1 = c.uint.decode(state)
26
26
 
@@ -36,18 +36,16 @@ const encoding1_1 = c.frame(encoding0)
36
36
 
37
37
  // @media/metadata
38
38
  const encoding1 = {
39
- preencode (state, m) {
39
+ preencode(state, m) {
40
40
  state.end++ // max flag is 4 so always one byte
41
41
 
42
42
  if (m.mimetype) c.string.preencode(state, m.mimetype)
43
43
  if (m.dimensions) encoding1_1.preencode(state, m.dimensions)
44
44
  if (m.duration) c.uint.preencode(state, m.duration)
45
45
  },
46
- encode (state, m) {
46
+ encode(state, m) {
47
47
  const flags =
48
- (m.mimetype ? 1 : 0) |
49
- (m.dimensions ? 2 : 0) |
50
- (m.duration ? 4 : 0)
48
+ (m.mimetype ? 1 : 0) | (m.dimensions ? 2 : 0) | (m.duration ? 4 : 0)
51
49
 
52
50
  c.uint.encode(state, flags)
53
51
 
@@ -55,7 +53,7 @@ const encoding1 = {
55
53
  if (m.dimensions) encoding1_1.encode(state, m.dimensions)
56
54
  if (m.duration) c.uint.encode(state, m.duration)
57
55
  },
58
- decode (state) {
56
+ decode(state) {
59
57
  const flags = c.uint.decode(state)
60
58
 
61
59
  return {
@@ -71,18 +69,16 @@ const encoding2_0 = c.frame(encoding1)
71
69
 
72
70
  // @media/file
73
71
  const encoding2 = {
74
- preencode (state, m) {
72
+ preencode(state, m) {
75
73
  state.end++ // max flag is 4 so always one byte
76
74
 
77
75
  if (m.metadata) encoding2_0.preencode(state, m.metadata)
78
76
  if (m.inlined) c.string.preencode(state, m.inlined)
79
77
  if (m.buffer) c.buffer.preencode(state, m.buffer)
80
78
  },
81
- encode (state, m) {
79
+ encode(state, m) {
82
80
  const flags =
83
- (m.metadata ? 1 : 0) |
84
- (m.inlined ? 2 : 0) |
85
- (m.buffer ? 4 : 0)
81
+ (m.metadata ? 1 : 0) | (m.inlined ? 2 : 0) | (m.buffer ? 4 : 0)
86
82
 
87
83
  c.uint.encode(state, flags)
88
84
 
@@ -90,7 +86,7 @@ const encoding2 = {
90
86
  if (m.inlined) c.string.encode(state, m.inlined)
91
87
  if (m.buffer) c.buffer.encode(state, m.buffer)
92
88
  },
93
- decode (state) {
89
+ decode(state) {
94
90
  const flags = c.uint.decode(state)
95
91
 
96
92
  return {
@@ -103,7 +99,7 @@ const encoding2 = {
103
99
 
104
100
  // @media/create-preview-request
105
101
  const encoding3 = {
106
- preencode (state, m) {
102
+ preencode(state, m) {
107
103
  c.string.preencode(state, m.path)
108
104
  state.end++ // max flag is 16 so always one byte
109
105
 
@@ -113,7 +109,7 @@ const encoding3 = {
113
109
  if (m.format) c.string.preencode(state, m.format)
114
110
  if (m.encoding) c.string.preencode(state, m.encoding)
115
111
  },
116
- encode (state, m) {
112
+ encode(state, m) {
117
113
  const flags =
118
114
  (m.mimetype ? 1 : 0) |
119
115
  (m.maxWidth ? 2 : 0) |
@@ -130,7 +126,7 @@ const encoding3 = {
130
126
  if (m.format) c.string.encode(state, m.format)
131
127
  if (m.encoding) c.string.encode(state, m.encoding)
132
128
  },
133
- decode (state) {
129
+ decode(state) {
134
130
  const r0 = c.string.decode(state)
135
131
  const flags = c.uint.decode(state)
136
132
 
@@ -152,15 +148,15 @@ const encoding4_1 = c.frame(encoding2)
152
148
 
153
149
  // @media/create-preview-response
154
150
  const encoding4 = {
155
- preencode (state, m) {
151
+ preencode(state, m) {
156
152
  encoding4_0.preencode(state, m.metadata)
157
153
  encoding4_1.preencode(state, m.preview)
158
154
  },
159
- encode (state, m) {
155
+ encode(state, m) {
160
156
  encoding4_0.encode(state, m.metadata)
161
157
  encoding4_1.encode(state, m.preview)
162
158
  },
163
- decode (state) {
159
+ decode(state) {
164
160
  const r0 = encoding4_0.decode(state)
165
161
  const r1 = encoding4_1.decode(state)
166
162
 
@@ -173,18 +169,15 @@ const encoding4 = {
173
169
 
174
170
  // @media/decode-image-request
175
171
  const encoding5 = {
176
- preencode (state, m) {
172
+ preencode(state, m) {
177
173
  state.end++ // max flag is 4 so always one byte
178
174
 
179
175
  if (m.path) c.string.preencode(state, m.path)
180
176
  if (m.httpLink) c.string.preencode(state, m.httpLink)
181
177
  if (m.mimetype) c.string.preencode(state, m.mimetype)
182
178
  },
183
- encode (state, m) {
184
- const flags =
185
- (m.path ? 1 : 0) |
186
- (m.httpLink ? 2 : 0) |
187
- (m.mimetype ? 4 : 0)
179
+ encode(state, m) {
180
+ const flags = (m.path ? 1 : 0) | (m.httpLink ? 2 : 0) | (m.mimetype ? 4 : 0)
188
181
 
189
182
  c.uint.encode(state, flags)
190
183
 
@@ -192,7 +185,7 @@ const encoding5 = {
192
185
  if (m.httpLink) c.string.encode(state, m.httpLink)
193
186
  if (m.mimetype) c.string.encode(state, m.mimetype)
194
187
  },
195
- decode (state) {
188
+ decode(state) {
196
189
  const flags = c.uint.decode(state)
197
190
 
198
191
  return {
@@ -208,23 +201,21 @@ const encoding6_0 = encoding2_0
208
201
 
209
202
  // @media/decode-image-response
210
203
  const encoding6 = {
211
- preencode (state, m) {
204
+ preencode(state, m) {
212
205
  state.end++ // max flag is 2 so always one byte
213
206
 
214
207
  if (m.metadata) encoding6_0.preencode(state, m.metadata)
215
208
  if (m.data) c.buffer.preencode(state, m.data)
216
209
  },
217
- encode (state, m) {
218
- const flags =
219
- (m.metadata ? 1 : 0) |
220
- (m.data ? 2 : 0)
210
+ encode(state, m) {
211
+ const flags = (m.metadata ? 1 : 0) | (m.data ? 2 : 0)
221
212
 
222
213
  c.uint.encode(state, flags)
223
214
 
224
215
  if (m.metadata) encoding6_0.encode(state, m.metadata)
225
216
  if (m.data) c.buffer.encode(state, m.data)
226
217
  },
227
- decode (state) {
218
+ decode(state) {
228
219
  const flags = c.uint.decode(state)
229
220
 
230
221
  return {
@@ -234,51 +225,60 @@ const encoding6 = {
234
225
  }
235
226
  }
236
227
 
237
- function setVersion (v) {
228
+ function setVersion(v) {
238
229
  version = v
239
230
  }
240
231
 
241
- function encode (name, value, v = VERSION) {
232
+ function encode(name, value, v = VERSION) {
242
233
  version = v
243
234
  return c.encode(getEncoding(name), value)
244
235
  }
245
236
 
246
- function decode (name, buffer, v = VERSION) {
237
+ function decode(name, buffer, v = VERSION) {
247
238
  version = v
248
239
  return c.decode(getEncoding(name), buffer)
249
240
  }
250
241
 
251
- function getEnum (name) {
242
+ function getEnum(name) {
252
243
  switch (name) {
253
- default: throw new Error('Enum not found ' + name)
244
+ default:
245
+ throw new Error('Enum not found ' + name)
254
246
  }
255
247
  }
256
248
 
257
- function getEncoding (name) {
249
+ function getEncoding(name) {
258
250
  switch (name) {
259
- case '@media/dimensions': return encoding0
260
- case '@media/metadata': return encoding1
261
- case '@media/file': return encoding2
262
- case '@media/create-preview-request': return encoding3
263
- case '@media/create-preview-response': return encoding4
264
- case '@media/decode-image-request': return encoding5
265
- case '@media/decode-image-response': return encoding6
266
- default: throw new Error('Encoder not found ' + name)
251
+ case '@media/dimensions':
252
+ return encoding0
253
+ case '@media/metadata':
254
+ return encoding1
255
+ case '@media/file':
256
+ return encoding2
257
+ case '@media/create-preview-request':
258
+ return encoding3
259
+ case '@media/create-preview-response':
260
+ return encoding4
261
+ case '@media/decode-image-request':
262
+ return encoding5
263
+ case '@media/decode-image-response':
264
+ return encoding6
265
+ default:
266
+ throw new Error('Encoder not found ' + name)
267
267
  }
268
268
  }
269
269
 
270
- function getStruct (name, v = VERSION) {
270
+ function getStruct(name, v = VERSION) {
271
271
  const enc = getEncoding(name)
272
272
  return {
273
- preencode (state, m) {
273
+ preencode(state, m) {
274
274
  version = v
275
275
  enc.preencode(state, m)
276
276
  },
277
- encode (state, m) {
277
+ encode(state, m) {
278
278
  version = v
279
279
  enc.encode(state, m)
280
280
  },
281
- decode (state) {
281
+ decode(state) {
282
282
  version = v
283
283
  return enc.decode(state)
284
284
  }
@@ -287,4 +287,13 @@ function getStruct (name, v = VERSION) {
287
287
 
288
288
  const resolveStruct = getStruct // compat
289
289
 
290
- export { resolveStruct, getStruct, getEnum, getEncoding, encode, decode, setVersion, version }
290
+ export {
291
+ resolveStruct,
292
+ getStruct,
293
+ getEnum,
294
+ getEncoding,
295
+ encode,
296
+ decode,
297
+ setVersion,
298
+ version
299
+ }
@@ -168,4 +168,4 @@
168
168
  ]
169
169
  }
170
170
  ]
171
- }
171
+ }
@@ -7,117 +7,131 @@ const media = schema.namespace('media')
7
7
 
8
8
  media.register({
9
9
  name: 'dimensions',
10
- fields: [{
11
- name: 'width',
12
- type: 'uint',
13
- required: true
14
- },
15
- {
16
- name: 'height',
17
- type: 'uint',
18
- required: true
19
- }]
10
+ fields: [
11
+ {
12
+ name: 'width',
13
+ type: 'uint',
14
+ required: true
15
+ },
16
+ {
17
+ name: 'height',
18
+ type: 'uint',
19
+ required: true
20
+ }
21
+ ]
20
22
  })
21
23
 
22
24
  media.register({
23
25
  name: 'metadata',
24
- fields: [{
25
- name: 'mimetype',
26
- type: 'string'
27
- },
28
- {
29
- name: 'dimensions',
30
- type: '@media/dimensions'
31
- },
32
- {
33
- name: 'duration',
34
- type: 'uint'
35
- }]
26
+ fields: [
27
+ {
28
+ name: 'mimetype',
29
+ type: 'string'
30
+ },
31
+ {
32
+ name: 'dimensions',
33
+ type: '@media/dimensions'
34
+ },
35
+ {
36
+ name: 'duration',
37
+ type: 'uint'
38
+ }
39
+ ]
36
40
  })
37
41
 
38
42
  media.register({
39
43
  name: 'file',
40
- fields: [{
41
- name: 'metadata',
42
- type: '@media/metadata'
43
- },
44
- {
45
- name: 'inlined',
46
- type: 'string'
47
- },
48
- {
49
- name: 'buffer',
50
- type: 'buffer'
51
- }]
44
+ fields: [
45
+ {
46
+ name: 'metadata',
47
+ type: '@media/metadata'
48
+ },
49
+ {
50
+ name: 'inlined',
51
+ type: 'string'
52
+ },
53
+ {
54
+ name: 'buffer',
55
+ type: 'buffer'
56
+ }
57
+ ]
52
58
  })
53
59
 
54
60
  media.register({
55
61
  name: 'create-preview-request',
56
- fields: [{
57
- name: 'path',
58
- type: 'string',
59
- required: true
60
- },
61
- {
62
- name: 'mimetype',
63
- type: 'string'
64
- },
65
- {
66
- name: 'maxWidth',
67
- type: 'uint'
68
- },
69
- {
70
- name: 'maxHeight',
71
- type: 'uint'
72
- },
73
- {
74
- name: 'format',
75
- type: 'string'
76
- },
77
- {
78
- name: 'encoding',
79
- type: 'string'
80
- }]
62
+ fields: [
63
+ {
64
+ name: 'path',
65
+ type: 'string',
66
+ required: true
67
+ },
68
+ {
69
+ name: 'mimetype',
70
+ type: 'string'
71
+ },
72
+ {
73
+ name: 'maxWidth',
74
+ type: 'uint'
75
+ },
76
+ {
77
+ name: 'maxHeight',
78
+ type: 'uint'
79
+ },
80
+ {
81
+ name: 'format',
82
+ type: 'string'
83
+ },
84
+ {
85
+ name: 'encoding',
86
+ type: 'string'
87
+ }
88
+ ]
81
89
  })
82
90
 
83
91
  media.register({
84
92
  name: 'create-preview-response',
85
- fields: [{
86
- name: 'metadata',
87
- type: '@media/metadata',
88
- required: true
89
- },
90
- {
91
- name: 'preview',
92
- type: '@media/file',
93
- required: true
94
- }]
93
+ fields: [
94
+ {
95
+ name: 'metadata',
96
+ type: '@media/metadata',
97
+ required: true
98
+ },
99
+ {
100
+ name: 'preview',
101
+ type: '@media/file',
102
+ required: true
103
+ }
104
+ ]
95
105
  })
96
106
 
97
107
  media.register({
98
108
  name: 'decode-image-request',
99
- fields: [{
100
- name: 'path',
101
- type: 'string'
102
- },
103
- {
104
- name: 'httpLink',
105
- type: 'string'
106
- },
107
- {
108
- name: 'mimetype',
109
- type: 'string'
110
- }]
109
+ fields: [
110
+ {
111
+ name: 'path',
112
+ type: 'string'
113
+ },
114
+ {
115
+ name: 'httpLink',
116
+ type: 'string'
117
+ },
118
+ {
119
+ name: 'mimetype',
120
+ type: 'string'
121
+ }
122
+ ]
111
123
  })
112
124
 
113
125
  media.register({
114
126
  name: 'decode-image-response',
115
- fields: [{
116
- name: 'metadata',
117
- type: '@media/metadata'
118
- },
119
- {
120
- name: 'data',
121
- type: 'buffer'
122
- }]
127
+ fields: [
128
+ {
129
+ name: 'metadata',
130
+ type: '@media/metadata'
131
+ },
132
+ {
133
+ name: 'data',
134
+ type: 'buffer'
135
+ }
136
+ ]
123
137
  })
package/worker/media.js CHANGED
@@ -10,7 +10,14 @@ const DEFAULT_PREVIEW_FORMAT = 'image/webp'
10
10
 
11
11
  const animatableMimetypes = ['image/webp']
12
12
 
13
- export async function createPreview ({ path, mimetype, maxWidth, maxHeight, format, encoding }) {
13
+ export async function createPreview({
14
+ path,
15
+ mimetype,
16
+ maxWidth,
17
+ maxHeight,
18
+ format,
19
+ encoding
20
+ }) {
14
21
  mimetype = mimetype || getMimeType(path)
15
22
  format = format || DEFAULT_PREVIEW_FORMAT
16
23
 
@@ -18,7 +25,7 @@ export async function createPreview ({ path, mimetype, maxWidth, maxHeight, form
18
25
  const rgba = await decodeImageToRGBA(buffer, mimetype)
19
26
  const { width, height } = rgba
20
27
 
21
- const { dimensions, rgba: maybeResizedRGBA } = await resizeRGBA(rgba, width, height, maxWidth, maxHeight)
28
+ const maybeResizedRGBA = await resizeRGBA(rgba, maxWidth, maxHeight)
22
29
 
23
30
  const encoded = await encodeImageFromRGBA(maybeResizedRGBA, format, encoding)
24
31
 
@@ -27,13 +34,19 @@ export async function createPreview ({ path, mimetype, maxWidth, maxHeight, form
27
34
  dimensions: { width, height }
28
35
  },
29
36
  preview: {
30
- metadata: { mimetype: format, dimensions },
37
+ metadata: {
38
+ mimetype: format,
39
+ dimensions: {
40
+ width: maybeResizedRGBA.width,
41
+ height: maybeResizedRGBA.height
42
+ }
43
+ },
31
44
  ...encoded
32
45
  }
33
46
  }
34
47
  }
35
48
 
36
- export async function decodeImage ({ path, httpLink, mimetype }) {
49
+ export async function decodeImage({ path, httpLink, mimetype }) {
37
50
  let buffer
38
51
 
39
52
  if (path) {
@@ -54,15 +67,18 @@ export async function decodeImage ({ path, httpLink, mimetype }) {
54
67
  }
55
68
  }
56
69
 
57
- async function decodeImageToRGBA (buffer, mimetype) {
70
+ async function decodeImageToRGBA(buffer, mimetype) {
58
71
  let rgba
59
72
 
60
73
  const codec = await importCodec(mimetype)
61
74
 
62
75
  if (animatableMimetypes.includes(mimetype)) {
63
- const { frames, width, height } = codec.decodeAnimated(buffer)
64
- const { data } = frames.next().value
65
- rgba = { width, height, data }
76
+ const { width, height, loops, frames } = codec.decodeAnimated(buffer)
77
+ const data = []
78
+ for (const frame of frames) {
79
+ data.push(frame)
80
+ }
81
+ rgba = { width, height, loops, frames: data }
66
82
  } else {
67
83
  rgba = codec.decode(buffer)
68
84
  }
@@ -70,26 +86,52 @@ async function decodeImageToRGBA (buffer, mimetype) {
70
86
  return rgba
71
87
  }
72
88
 
73
- async function encodeImageFromRGBA (rgba, format, encoding) {
89
+ async function encodeImageFromRGBA(rgba, format, encoding) {
74
90
  const codec = await importCodec(format)
75
- const encoded = codec.encode(rgba)
91
+
92
+ let encoded
93
+ if (Array.isArray(rgba.frames)) {
94
+ encoded = codec.encodeAnimated(rgba)
95
+ } else {
96
+ encoded = codec.encode(rgba)
97
+ }
76
98
 
77
99
  return encoding === 'base64'
78
100
  ? { inlined: b4a.toString(encoded, 'base64') }
79
101
  : { buffer: encoded }
80
102
  }
81
103
 
82
- async function resizeRGBA (rgba, width, height, maxWidth, maxHeight) {
83
- let maybeResizedRGBA, dimensions
104
+ async function resizeRGBA(rgba, maxWidth, maxHeight) {
105
+ const { width, height } = rgba
106
+
107
+ let maybeResizedRGBA
84
108
 
85
109
  if (maxWidth && maxHeight && (width > maxWidth || height > maxHeight)) {
86
110
  const { resize } = await import('bare-image-resample')
87
- dimensions = calculateFitDimensions(width, height, maxWidth, maxHeight)
88
- maybeResizedRGBA = resize(rgba, dimensions.width, dimensions.height)
111
+ const dimensions = calculateFitDimensions(
112
+ width,
113
+ height,
114
+ maxWidth,
115
+ maxHeight
116
+ )
117
+ if (Array.isArray(rgba.frames)) {
118
+ const frames = []
119
+ for (const frame of rgba.frames) {
120
+ const resized = resize(frame, dimensions.width, dimensions.height)
121
+ frames.push({ ...resized, timestamp: frame.timestamp })
122
+ }
123
+ maybeResizedRGBA = {
124
+ width: frames[0].width,
125
+ height: frames[0].height,
126
+ loops: rgba.loops,
127
+ frames
128
+ }
129
+ } else {
130
+ maybeResizedRGBA = resize(rgba, dimensions.width, dimensions.height)
131
+ }
89
132
  } else {
90
- dimensions = { width, height }
91
133
  maybeResizedRGBA = rgba
92
134
  }
93
135
 
94
- return { dimensions, rgba: maybeResizedRGBA }
136
+ return maybeResizedRGBA
95
137
  }
package/worker/util.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export const log = (...args) => console.log('[bare-media]', ...args)
2
2
 
3
- export function calculateFitDimensions (width, height, maxWidth, maxHeight) {
3
+ export function calculateFitDimensions(width, height, maxWidth, maxHeight) {
4
4
  if (width <= maxWidth && height <= maxHeight) {
5
5
  return { width, height }
6
6
  }