bare-media 1.8.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/README.md +91 -58
- package/index.js +3 -5
- package/package.json +19 -19
- package/src/codecs.js +26 -0
- package/src/image.js +262 -0
- package/src/util.js +30 -0
- package/src/video.js +112 -0
- package/types.js +36 -0
- package/client.js +0 -78
- package/shared/codecs.js +0 -26
- package/shared/spec/build.js +0 -34
- package/shared/spec/constants.js +0 -2
- package/shared/spec/hrpc/hrpc.json +0 -44
- package/shared/spec/hrpc/index.js +0 -164
- package/shared/spec/hrpc/messages.js +0 -440
- package/shared/spec/schema/index.js +0 -440
- package/shared/spec/schema/schema.json +0 -266
- package/shared/spec/schema.js +0 -212
- package/worker/index.js +0 -25
- package/worker/media.js +0 -274
- package/worker/util.js +0 -42
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', 'cropImage']
|
|
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
|
-
}
|
package/shared/spec/build.js
DELETED
|
@@ -1,34 +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
|
-
ns.register({
|
|
29
|
-
name: 'crop-image',
|
|
30
|
-
request: { name: '@media/crop-image-request', stream: false },
|
|
31
|
-
response: { name: '@media/crop-image-response', stream: false }
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
HRPCBuilder.toDisk(builder)
|
package/shared/spec/constants.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 2,
|
|
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
|
-
"id": 2,
|
|
32
|
-
"name": "@media/crop-image",
|
|
33
|
-
"request": {
|
|
34
|
-
"name": "@media/crop-image-request",
|
|
35
|
-
"stream": false
|
|
36
|
-
},
|
|
37
|
-
"response": {
|
|
38
|
-
"name": "@media/crop-image-response",
|
|
39
|
-
"stream": false
|
|
40
|
-
},
|
|
41
|
-
"version": 2
|
|
42
|
-
}
|
|
43
|
-
]
|
|
44
|
-
}
|
|
@@ -1,164 +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
|
-
['@media/crop-image', 2],
|
|
14
|
-
[2, '@media/crop-image']
|
|
15
|
-
])
|
|
16
|
-
|
|
17
|
-
class HRPC {
|
|
18
|
-
constructor(stream) {
|
|
19
|
-
this._stream = stream
|
|
20
|
-
this._handlers = []
|
|
21
|
-
this._requestEncodings = new Map([
|
|
22
|
-
['@media/create-preview', getEncoding('@media/create-preview-request')],
|
|
23
|
-
['@media/decode-image', getEncoding('@media/decode-image-request')],
|
|
24
|
-
['@media/crop-image', getEncoding('@media/crop-image-request')]
|
|
25
|
-
])
|
|
26
|
-
this._responseEncodings = new Map([
|
|
27
|
-
['@media/create-preview', getEncoding('@media/create-preview-response')],
|
|
28
|
-
['@media/decode-image', getEncoding('@media/decode-image-response')],
|
|
29
|
-
['@media/crop-image', getEncoding('@media/crop-image-response')]
|
|
30
|
-
])
|
|
31
|
-
this._rpc = new RPC(stream, async (req) => {
|
|
32
|
-
const command = methods.get(req.command)
|
|
33
|
-
const responseEncoding = this._responseEncodings.get(command)
|
|
34
|
-
const requestEncoding = this._requestEncodings.get(command)
|
|
35
|
-
if (this._requestIsSend(command)) {
|
|
36
|
-
const request = req.data ? c.decode(requestEncoding, req.data) : null
|
|
37
|
-
await this._handlers[command](request)
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
if (!this._requestIsStream(command) && !this._responseIsStream(command)) {
|
|
41
|
-
const request = req.data ? c.decode(requestEncoding, req.data) : null
|
|
42
|
-
const response = await this._handlers[command](request)
|
|
43
|
-
req.reply(c.encode(responseEncoding, response))
|
|
44
|
-
}
|
|
45
|
-
if (!this._requestIsStream(command) && this._responseIsStream(command)) {
|
|
46
|
-
const request = req.data ? c.decode(requestEncoding, req.data) : null
|
|
47
|
-
const responseStream = new RPCStream(
|
|
48
|
-
null,
|
|
49
|
-
null,
|
|
50
|
-
req.createResponseStream(),
|
|
51
|
-
responseEncoding
|
|
52
|
-
)
|
|
53
|
-
responseStream.data = request
|
|
54
|
-
await this._handlers[command](responseStream)
|
|
55
|
-
}
|
|
56
|
-
if (this._requestIsStream(command) && !this._responseIsStream(command)) {
|
|
57
|
-
const requestStream = new RPCRequestStream(
|
|
58
|
-
req,
|
|
59
|
-
responseEncoding,
|
|
60
|
-
req.createRequestStream(),
|
|
61
|
-
requestEncoding
|
|
62
|
-
)
|
|
63
|
-
const response = await this._handlers[command](requestStream)
|
|
64
|
-
req.reply(c.encode(responseEncoding, response))
|
|
65
|
-
}
|
|
66
|
-
if (this._requestIsStream(command) && this._responseIsStream(command)) {
|
|
67
|
-
const requestStream = new RPCRequestStream(
|
|
68
|
-
req,
|
|
69
|
-
responseEncoding,
|
|
70
|
-
req.createRequestStream(),
|
|
71
|
-
requestEncoding,
|
|
72
|
-
req.createResponseStream(),
|
|
73
|
-
responseEncoding
|
|
74
|
-
)
|
|
75
|
-
await this._handlers[command](requestStream)
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async _call(name, args) {
|
|
81
|
-
const requestEncoding = this._requestEncodings.get(name)
|
|
82
|
-
const responseEncoding = this._responseEncodings.get(name)
|
|
83
|
-
const request = this._rpc.request(methods.get(name))
|
|
84
|
-
const encoded = c.encode(requestEncoding, args)
|
|
85
|
-
request.send(encoded)
|
|
86
|
-
return c.decode(responseEncoding, await request.reply())
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
_callSync(name, args) {
|
|
90
|
-
const requestEncoding = this._requestEncodings.get(name)
|
|
91
|
-
const responseEncoding = this._responseEncodings.get(name)
|
|
92
|
-
const request = this._rpc.request(methods.get(name))
|
|
93
|
-
if (this._requestIsSend(name)) {
|
|
94
|
-
const encoded = c.encode(requestEncoding, args)
|
|
95
|
-
request.send(encoded)
|
|
96
|
-
}
|
|
97
|
-
if (!this._requestIsStream(name) && this._responseIsStream(name)) {
|
|
98
|
-
const encoded = c.encode(requestEncoding, args)
|
|
99
|
-
request.send(encoded)
|
|
100
|
-
return new RPCStream(request.createResponseStream(), responseEncoding)
|
|
101
|
-
}
|
|
102
|
-
if (this._requestIsStream(name) && !this._responseIsStream(name)) {
|
|
103
|
-
return new RPCRequestStream(
|
|
104
|
-
request,
|
|
105
|
-
responseEncoding,
|
|
106
|
-
null,
|
|
107
|
-
null,
|
|
108
|
-
request.createRequestStream(),
|
|
109
|
-
requestEncoding
|
|
110
|
-
)
|
|
111
|
-
}
|
|
112
|
-
if (this._requestIsStream(name) && this._responseIsStream(name)) {
|
|
113
|
-
return new RPCRequestStream(
|
|
114
|
-
request,
|
|
115
|
-
responseEncoding,
|
|
116
|
-
request.createResponseStream(),
|
|
117
|
-
responseEncoding,
|
|
118
|
-
request.createRequestStream(),
|
|
119
|
-
requestEncoding
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async createPreview(args) {
|
|
125
|
-
return this._call('@media/create-preview', args)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async decodeImage(args) {
|
|
129
|
-
return this._call('@media/decode-image', args)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async cropImage(args) {
|
|
133
|
-
return this._call('@media/crop-image', args)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
onCreatePreview(responseFn) {
|
|
137
|
-
this._handlers['@media/create-preview'] = responseFn
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
onDecodeImage(responseFn) {
|
|
141
|
-
this._handlers['@media/decode-image'] = responseFn
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
onCropImage(responseFn) {
|
|
145
|
-
this._handlers['@media/crop-image'] = responseFn
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
_requestIsStream(command) {
|
|
149
|
-
return [].includes(command)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
_responseIsStream(command) {
|
|
153
|
-
return [].includes(command)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// prettier-ignore-start
|
|
157
|
-
_requestIsSend(command) {
|
|
158
|
-
return [
|
|
159
|
-
// prettier-ignore
|
|
160
|
-
].includes(command)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export default HRPC
|