bare-media 1.7.0 → 2.0.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/types.js ADDED
@@ -0,0 +1,36 @@
1
+ export const IMAGE = {
2
+ AVIF: 'image/avif',
3
+ GIF: 'image/gif',
4
+ BMP: 'image/bmp',
5
+ HEIC: 'image/heic',
6
+ HEIF: 'image/heif',
7
+ JPEG: 'image/jpeg',
8
+ JPG: 'image/jpg',
9
+ PNG: 'image/png',
10
+ TIF: 'image/tif',
11
+ TIFF: 'image/tiff',
12
+ WEBP: 'image/webp',
13
+ X_MS_BMP: 'image/bmp'
14
+ }
15
+
16
+ export const supportedImageMimetypes = Object.values(IMAGE)
17
+
18
+ export const supportedVideoMimetypes = [
19
+ 'video/mp4',
20
+ 'video/webm',
21
+ 'video/quicktime',
22
+ 'video/x-matroska',
23
+ 'video/x-msvideo'
24
+ ]
25
+
26
+ export function isImageSupported(mimetype) {
27
+ return supportedImageMimetypes.includes(mimetype)
28
+ }
29
+
30
+ export function isVideoSupported(mimetype) {
31
+ return supportedVideoMimetypes.includes(mimetype)
32
+ }
33
+
34
+ export function isMediaSupported(mimetype) {
35
+ return isImageSupported(mimetype) || isVideoSupported(mimetype)
36
+ }
package/client.js DELETED
@@ -1,78 +0,0 @@
1
- import { spawn } from 'cross-worker/client'
2
- import ReadyResource from 'ready-resource'
3
-
4
- import HRPC from './shared/spec/hrpc/index.js'
5
- import { isCodecSupported } from './shared/codecs.js'
6
-
7
- export class WorkerClient extends ReadyResource {
8
- worker = null
9
- rpc = null
10
- opts = null
11
-
12
- constructor(opts) {
13
- super()
14
- this.initialize(opts)
15
- this.#attachMethods()
16
- }
17
-
18
- initialize({
19
- filename = 'node_modules/bare-media/worker/index.js',
20
- requireSource,
21
- args
22
- } = {}) {
23
- this.opts = { filename, requireSource, args }
24
- }
25
-
26
- #attachMethods() {
27
- const methods = ['createPreview', 'decodeImage']
28
-
29
- for (const method of methods) {
30
- this[method] = async (...args) => {
31
- await this.ready()
32
- return this.rpc[method](...args)
33
- }
34
- }
35
- }
36
-
37
- async _open() {
38
- await this.#run()
39
- }
40
-
41
- async _close() {
42
- this.worker?.IPC.end()
43
- }
44
-
45
- #reset() {
46
- this.opening = null
47
- this.closing = null
48
-
49
- this.opened = false
50
- this.closed = false
51
-
52
- this.worker = null
53
- this.rpc = null
54
- }
55
-
56
- async #run() {
57
- const { filename, requireSource, args } = this.opts
58
- const source = requireSource?.()
59
- this.worker = await spawn(filename, source, args)
60
-
61
- const ipc = this.worker.IPC
62
-
63
- ipc.on('end', () => ipc.end())
64
- ipc.on('close', () => {
65
- this.#reset()
66
- this.onClose?.()
67
- console.error(
68
- '[bare-media] Worker has exited. IPC channel closed unexpectedly.'
69
- )
70
- })
71
-
72
- this.rpc = new HRPC(ipc)
73
- }
74
-
75
- isCodecSupported(mimetype) {
76
- return isCodecSupported(mimetype)
77
- }
78
- }
package/shared/codecs.js DELETED
@@ -1,26 +0,0 @@
1
- export const codecs = {
2
- 'image/jpeg': () => import('bare-jpeg'),
3
- 'image/jpg': () => import('bare-jpeg'),
4
- 'image/avif': () => import('bare-heif'),
5
- 'image/heic': () => import('bare-heif'),
6
- 'image/heif': () => import('bare-heif'),
7
- 'image/webp': () => import('bare-webp'),
8
- 'image/png': () => import('bare-png'),
9
- 'image/tif': () => import('bare-tiff'),
10
- 'image/tiff': () => import('bare-tiff'),
11
- 'image/gif': () => import('bare-gif')
12
- }
13
-
14
- export function isCodecSupported(mimetype) {
15
- return mimetype in codecs
16
- }
17
-
18
- export async function importCodec(mimetype) {
19
- const codecImport = codecs[mimetype]
20
- if (!codecImport) throw new Error(`No codec for ${mimetype}`)
21
- return await codecImport()
22
- }
23
-
24
- export function supportsQuality(mimetype) {
25
- return { 'image/webp': true, 'image/jpeg': true }[mimetype] || false
26
- }
@@ -1,28 +0,0 @@
1
- import HRPCBuilder from 'hrpc'
2
- import Hyperschema from 'hyperschema'
3
-
4
- import { schema } from './schema'
5
- import { SCHEMA_DIR, HRPC_DIR } from './constants'
6
-
7
- // Schema
8
-
9
- Hyperschema.toDisk(schema)
10
-
11
- // HRPC
12
-
13
- const builder = HRPCBuilder.from(SCHEMA_DIR, HRPC_DIR)
14
- const ns = builder.namespace('media')
15
-
16
- ns.register({
17
- name: 'create-preview',
18
- request: { name: '@media/create-preview-request', stream: false },
19
- response: { name: '@media/create-preview-response', stream: false }
20
- })
21
-
22
- ns.register({
23
- name: 'decode-image',
24
- request: { name: '@media/decode-image-request', stream: false },
25
- response: { name: '@media/decode-image-response', stream: false }
26
- })
27
-
28
- HRPCBuilder.toDisk(builder)
@@ -1,2 +0,0 @@
1
- export const SCHEMA_DIR = './schema'
2
- export const HRPC_DIR = './hrpc'
@@ -1,31 +0,0 @@
1
- {
2
- "version": 1,
3
- "schema": [
4
- {
5
- "id": 0,
6
- "name": "@media/create-preview",
7
- "request": {
8
- "name": "@media/create-preview-request",
9
- "stream": false
10
- },
11
- "response": {
12
- "name": "@media/create-preview-response",
13
- "stream": false
14
- },
15
- "version": 1
16
- },
17
- {
18
- "id": 1,
19
- "name": "@media/decode-image",
20
- "request": {
21
- "name": "@media/decode-image-request",
22
- "stream": false
23
- },
24
- "response": {
25
- "name": "@media/decode-image-response",
26
- "stream": false
27
- },
28
- "version": 1
29
- }
30
- ]
31
- }
@@ -1,152 +0,0 @@
1
- // This file is autogenerated by the hrpc compiler
2
- /* eslint-disable camelcase */
3
- /* eslint-disable space-before-function-paren */
4
-
5
- import { c, RPC, RPCStream, RPCRequestStream } from 'hrpc/runtime'
6
- import { getEncoding } from './messages.js'
7
-
8
- const methods = new Map([
9
- ['@media/create-preview', 0],
10
- [0, '@media/create-preview'],
11
- ['@media/decode-image', 1],
12
- [1, '@media/decode-image']
13
- ])
14
-
15
- class HRPC {
16
- constructor(stream) {
17
- this._stream = stream
18
- this._handlers = []
19
- this._requestEncodings = new Map([
20
- ['@media/create-preview', getEncoding('@media/create-preview-request')],
21
- ['@media/decode-image', getEncoding('@media/decode-image-request')]
22
- ])
23
- this._responseEncodings = new Map([
24
- ['@media/create-preview', getEncoding('@media/create-preview-response')],
25
- ['@media/decode-image', getEncoding('@media/decode-image-response')]
26
- ])
27
- this._rpc = new RPC(stream, async (req) => {
28
- const command = methods.get(req.command)
29
- const responseEncoding = this._responseEncodings.get(command)
30
- const requestEncoding = this._requestEncodings.get(command)
31
- if (this._requestIsSend(command)) {
32
- const request = req.data ? c.decode(requestEncoding, req.data) : null
33
- await this._handlers[command](request)
34
- return
35
- }
36
- if (!this._requestIsStream(command) && !this._responseIsStream(command)) {
37
- const request = req.data ? c.decode(requestEncoding, req.data) : null
38
- const response = await this._handlers[command](request)
39
- req.reply(c.encode(responseEncoding, response))
40
- }
41
- if (!this._requestIsStream(command) && this._responseIsStream(command)) {
42
- const request = req.data ? c.decode(requestEncoding, req.data) : null
43
- const responseStream = new RPCStream(
44
- null,
45
- null,
46
- req.createResponseStream(),
47
- responseEncoding
48
- )
49
- responseStream.data = request
50
- await this._handlers[command](responseStream)
51
- }
52
- if (this._requestIsStream(command) && !this._responseIsStream(command)) {
53
- const requestStream = new RPCRequestStream(
54
- req,
55
- responseEncoding,
56
- req.createRequestStream(),
57
- requestEncoding
58
- )
59
- const response = await this._handlers[command](requestStream)
60
- req.reply(c.encode(responseEncoding, response))
61
- }
62
- if (this._requestIsStream(command) && this._responseIsStream(command)) {
63
- const requestStream = new RPCRequestStream(
64
- req,
65
- responseEncoding,
66
- req.createRequestStream(),
67
- requestEncoding,
68
- req.createResponseStream(),
69
- responseEncoding
70
- )
71
- await this._handlers[command](requestStream)
72
- }
73
- })
74
- }
75
-
76
- async _call(name, args) {
77
- const requestEncoding = this._requestEncodings.get(name)
78
- const responseEncoding = this._responseEncodings.get(name)
79
- const request = this._rpc.request(methods.get(name))
80
- const encoded = c.encode(requestEncoding, args)
81
- request.send(encoded)
82
- return c.decode(responseEncoding, await request.reply())
83
- }
84
-
85
- _callSync(name, args) {
86
- const requestEncoding = this._requestEncodings.get(name)
87
- const responseEncoding = this._responseEncodings.get(name)
88
- const request = this._rpc.request(methods.get(name))
89
- if (this._requestIsSend(name)) {
90
- const encoded = c.encode(requestEncoding, args)
91
- request.send(encoded)
92
- }
93
- if (!this._requestIsStream(name) && this._responseIsStream(name)) {
94
- const encoded = c.encode(requestEncoding, args)
95
- request.send(encoded)
96
- return new RPCStream(request.createResponseStream(), responseEncoding)
97
- }
98
- if (this._requestIsStream(name) && !this._responseIsStream(name)) {
99
- return new RPCRequestStream(
100
- request,
101
- responseEncoding,
102
- null,
103
- null,
104
- request.createRequestStream(),
105
- requestEncoding
106
- )
107
- }
108
- if (this._requestIsStream(name) && this._responseIsStream(name)) {
109
- return new RPCRequestStream(
110
- request,
111
- responseEncoding,
112
- request.createResponseStream(),
113
- responseEncoding,
114
- request.createRequestStream(),
115
- requestEncoding
116
- )
117
- }
118
- }
119
-
120
- async createPreview(args) {
121
- return this._call('@media/create-preview', args)
122
- }
123
-
124
- async decodeImage(args) {
125
- return this._call('@media/decode-image', args)
126
- }
127
-
128
- onCreatePreview(responseFn) {
129
- this._handlers['@media/create-preview'] = responseFn
130
- }
131
-
132
- onDecodeImage(responseFn) {
133
- this._handlers['@media/decode-image'] = responseFn
134
- }
135
-
136
- _requestIsStream(command) {
137
- return [].includes(command)
138
- }
139
-
140
- _responseIsStream(command) {
141
- return [].includes(command)
142
- }
143
-
144
- // prettier-ignore-start
145
- _requestIsSend(command) {
146
- return [
147
- // prettier-ignore
148
- ].includes(command)
149
- }
150
- }
151
-
152
- export default HRPC
@@ -1,334 +0,0 @@
1
- // This file is autogenerated by the hyperschema compiler
2
- // Schema Version: 1
3
- /* eslint-disable camelcase */
4
- /* eslint-disable quotes */
5
-
6
- import { c } from 'hyperschema/runtime'
7
-
8
- const VERSION = 1
9
-
10
- // eslint-disable-next-line no-unused-vars
11
- let version = VERSION
12
-
13
- // @media/dimensions
14
- const encoding0 = {
15
- preencode(state, m) {
16
- c.uint.preencode(state, m.width)
17
- c.uint.preencode(state, m.height)
18
- },
19
- encode(state, m) {
20
- c.uint.encode(state, m.width)
21
- c.uint.encode(state, m.height)
22
- },
23
- decode(state) {
24
- const r0 = c.uint.decode(state)
25
- const r1 = c.uint.decode(state)
26
-
27
- return {
28
- width: r0,
29
- height: r1
30
- }
31
- }
32
- }
33
-
34
- // @media/metadata.dimensions
35
- const encoding1_1 = c.frame(encoding0)
36
-
37
- // @media/metadata
38
- const encoding1 = {
39
- preencode(state, m) {
40
- state.end++ // max flag is 4 so always one byte
41
-
42
- if (m.mimetype) c.string.preencode(state, m.mimetype)
43
- if (m.dimensions) encoding1_1.preencode(state, m.dimensions)
44
- if (m.duration) c.uint.preencode(state, m.duration)
45
- },
46
- encode(state, m) {
47
- const flags =
48
- (m.mimetype ? 1 : 0) | (m.dimensions ? 2 : 0) | (m.duration ? 4 : 0)
49
-
50
- c.uint.encode(state, flags)
51
-
52
- if (m.mimetype) c.string.encode(state, m.mimetype)
53
- if (m.dimensions) encoding1_1.encode(state, m.dimensions)
54
- if (m.duration) c.uint.encode(state, m.duration)
55
- },
56
- decode(state) {
57
- const flags = c.uint.decode(state)
58
-
59
- return {
60
- mimetype: (flags & 1) !== 0 ? c.string.decode(state) : null,
61
- dimensions: (flags & 2) !== 0 ? encoding1_1.decode(state) : null,
62
- duration: (flags & 4) !== 0 ? c.uint.decode(state) : 0
63
- }
64
- }
65
- }
66
-
67
- // @media/file.metadata
68
- const encoding2_0 = c.frame(encoding1)
69
-
70
- // @media/file
71
- const encoding2 = {
72
- preencode(state, m) {
73
- state.end++ // max flag is 4 so always one byte
74
-
75
- if (m.metadata) encoding2_0.preencode(state, m.metadata)
76
- if (m.inlined) c.string.preencode(state, m.inlined)
77
- if (m.buffer) c.buffer.preencode(state, m.buffer)
78
- },
79
- encode(state, m) {
80
- const flags =
81
- (m.metadata ? 1 : 0) | (m.inlined ? 2 : 0) | (m.buffer ? 4 : 0)
82
-
83
- c.uint.encode(state, flags)
84
-
85
- if (m.metadata) encoding2_0.encode(state, m.metadata)
86
- if (m.inlined) c.string.encode(state, m.inlined)
87
- if (m.buffer) c.buffer.encode(state, m.buffer)
88
- },
89
- decode(state) {
90
- const flags = c.uint.decode(state)
91
-
92
- return {
93
- metadata: (flags & 1) !== 0 ? encoding2_0.decode(state) : null,
94
- inlined: (flags & 2) !== 0 ? c.string.decode(state) : null,
95
- buffer: (flags & 4) !== 0 ? c.buffer.decode(state) : null
96
- }
97
- }
98
- }
99
-
100
- // @media/create-preview-request
101
- const encoding3 = {
102
- preencode(state, m) {
103
- const flags =
104
- (m.path ? 1 : 0) |
105
- (m.httpLink ? 2 : 0) |
106
- (m.buffer ? 4 : 0) |
107
- (m.mimetype ? 8 : 0) |
108
- (m.maxWidth ? 16 : 0) |
109
- (m.maxHeight ? 32 : 0) |
110
- (m.maxFrames ? 64 : 0) |
111
- (m.maxBytes ? 128 : 0) |
112
- (m.format ? 256 : 0) |
113
- (m.encoding ? 512 : 0)
114
-
115
- c.uint.preencode(state, flags)
116
-
117
- if (m.path) c.string.preencode(state, m.path)
118
- if (m.httpLink) c.string.preencode(state, m.httpLink)
119
- if (m.buffer) c.buffer.preencode(state, m.buffer)
120
- if (m.mimetype) c.string.preencode(state, m.mimetype)
121
- if (m.maxWidth) c.uint.preencode(state, m.maxWidth)
122
- if (m.maxHeight) c.uint.preencode(state, m.maxHeight)
123
- if (m.maxFrames) c.uint.preencode(state, m.maxFrames)
124
- if (m.maxBytes) c.uint.preencode(state, m.maxBytes)
125
- if (m.format) c.string.preencode(state, m.format)
126
- if (m.encoding) c.string.preencode(state, m.encoding)
127
- },
128
- encode(state, m) {
129
- const flags =
130
- (m.path ? 1 : 0) |
131
- (m.httpLink ? 2 : 0) |
132
- (m.buffer ? 4 : 0) |
133
- (m.mimetype ? 8 : 0) |
134
- (m.maxWidth ? 16 : 0) |
135
- (m.maxHeight ? 32 : 0) |
136
- (m.maxFrames ? 64 : 0) |
137
- (m.maxBytes ? 128 : 0) |
138
- (m.format ? 256 : 0) |
139
- (m.encoding ? 512 : 0)
140
-
141
- c.uint.encode(state, flags)
142
-
143
- if (m.path) c.string.encode(state, m.path)
144
- if (m.httpLink) c.string.encode(state, m.httpLink)
145
- if (m.buffer) c.buffer.encode(state, m.buffer)
146
- if (m.mimetype) c.string.encode(state, m.mimetype)
147
- if (m.maxWidth) c.uint.encode(state, m.maxWidth)
148
- if (m.maxHeight) c.uint.encode(state, m.maxHeight)
149
- if (m.maxFrames) c.uint.encode(state, m.maxFrames)
150
- if (m.maxBytes) c.uint.encode(state, m.maxBytes)
151
- if (m.format) c.string.encode(state, m.format)
152
- if (m.encoding) c.string.encode(state, m.encoding)
153
- },
154
- decode(state) {
155
- const flags = c.uint.decode(state)
156
-
157
- return {
158
- path: (flags & 1) !== 0 ? c.string.decode(state) : null,
159
- httpLink: (flags & 2) !== 0 ? c.string.decode(state) : null,
160
- buffer: (flags & 4) !== 0 ? c.buffer.decode(state) : null,
161
- mimetype: (flags & 8) !== 0 ? c.string.decode(state) : null,
162
- maxWidth: (flags & 16) !== 0 ? c.uint.decode(state) : 0,
163
- maxHeight: (flags & 32) !== 0 ? c.uint.decode(state) : 0,
164
- maxFrames: (flags & 64) !== 0 ? c.uint.decode(state) : 0,
165
- maxBytes: (flags & 128) !== 0 ? c.uint.decode(state) : 0,
166
- format: (flags & 256) !== 0 ? c.string.decode(state) : null,
167
- encoding: (flags & 512) !== 0 ? c.string.decode(state) : null
168
- }
169
- }
170
- }
171
-
172
- // @media/create-preview-response.metadata
173
- const encoding4_0 = encoding2_0
174
- // @media/create-preview-response.preview
175
- const encoding4_1 = c.frame(encoding2)
176
-
177
- // @media/create-preview-response
178
- const encoding4 = {
179
- preencode(state, m) {
180
- encoding4_0.preencode(state, m.metadata)
181
- encoding4_1.preencode(state, m.preview)
182
- },
183
- encode(state, m) {
184
- encoding4_0.encode(state, m.metadata)
185
- encoding4_1.encode(state, m.preview)
186
- },
187
- decode(state) {
188
- const r0 = encoding4_0.decode(state)
189
- const r1 = encoding4_1.decode(state)
190
-
191
- return {
192
- metadata: r0,
193
- preview: r1
194
- }
195
- }
196
- }
197
-
198
- // @media/decode-image-request
199
- const encoding5 = {
200
- preencode(state, m) {
201
- state.end++ // max flag is 8 so always one byte
202
-
203
- if (m.path) c.string.preencode(state, m.path)
204
- if (m.httpLink) c.string.preencode(state, m.httpLink)
205
- if (m.buffer) c.buffer.preencode(state, m.buffer)
206
- if (m.mimetype) c.string.preencode(state, m.mimetype)
207
- },
208
- encode(state, m) {
209
- const flags =
210
- (m.path ? 1 : 0) |
211
- (m.httpLink ? 2 : 0) |
212
- (m.buffer ? 4 : 0) |
213
- (m.mimetype ? 8 : 0)
214
-
215
- c.uint.encode(state, flags)
216
-
217
- if (m.path) c.string.encode(state, m.path)
218
- if (m.httpLink) c.string.encode(state, m.httpLink)
219
- if (m.buffer) c.buffer.encode(state, m.buffer)
220
- if (m.mimetype) c.string.encode(state, m.mimetype)
221
- },
222
- decode(state) {
223
- const flags = c.uint.decode(state)
224
-
225
- return {
226
- path: (flags & 1) !== 0 ? c.string.decode(state) : null,
227
- httpLink: (flags & 2) !== 0 ? c.string.decode(state) : null,
228
- buffer: (flags & 4) !== 0 ? c.buffer.decode(state) : null,
229
- mimetype: (flags & 8) !== 0 ? c.string.decode(state) : null
230
- }
231
- }
232
- }
233
-
234
- // @media/decode-image-response.metadata
235
- const encoding6_0 = encoding2_0
236
-
237
- // @media/decode-image-response
238
- const encoding6 = {
239
- preencode(state, m) {
240
- state.end++ // max flag is 2 so always one byte
241
-
242
- if (m.metadata) encoding6_0.preencode(state, m.metadata)
243
- if (m.data) c.buffer.preencode(state, m.data)
244
- },
245
- encode(state, m) {
246
- const flags = (m.metadata ? 1 : 0) | (m.data ? 2 : 0)
247
-
248
- c.uint.encode(state, flags)
249
-
250
- if (m.metadata) encoding6_0.encode(state, m.metadata)
251
- if (m.data) c.buffer.encode(state, m.data)
252
- },
253
- decode(state) {
254
- const flags = c.uint.decode(state)
255
-
256
- return {
257
- metadata: (flags & 1) !== 0 ? encoding6_0.decode(state) : null,
258
- data: (flags & 2) !== 0 ? c.buffer.decode(state) : null
259
- }
260
- }
261
- }
262
-
263
- function setVersion(v) {
264
- version = v
265
- }
266
-
267
- function encode(name, value, v = VERSION) {
268
- version = v
269
- return c.encode(getEncoding(name), value)
270
- }
271
-
272
- function decode(name, buffer, v = VERSION) {
273
- version = v
274
- return c.decode(getEncoding(name), buffer)
275
- }
276
-
277
- function getEnum(name) {
278
- switch (name) {
279
- default:
280
- throw new Error('Enum not found ' + name)
281
- }
282
- }
283
-
284
- function getEncoding(name) {
285
- switch (name) {
286
- case '@media/dimensions':
287
- return encoding0
288
- case '@media/metadata':
289
- return encoding1
290
- case '@media/file':
291
- return encoding2
292
- case '@media/create-preview-request':
293
- return encoding3
294
- case '@media/create-preview-response':
295
- return encoding4
296
- case '@media/decode-image-request':
297
- return encoding5
298
- case '@media/decode-image-response':
299
- return encoding6
300
- default:
301
- throw new Error('Encoder not found ' + name)
302
- }
303
- }
304
-
305
- function getStruct(name, v = VERSION) {
306
- const enc = getEncoding(name)
307
- return {
308
- preencode(state, m) {
309
- version = v
310
- enc.preencode(state, m)
311
- },
312
- encode(state, m) {
313
- version = v
314
- enc.encode(state, m)
315
- },
316
- decode(state) {
317
- version = v
318
- return enc.decode(state)
319
- }
320
- }
321
- }
322
-
323
- const resolveStruct = getStruct // compat
324
-
325
- export {
326
- resolveStruct,
327
- getStruct,
328
- getEnum,
329
- getEncoding,
330
- encode,
331
- decode,
332
- setVersion,
333
- version
334
- }