@probityrules/jsmediatags 4.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/CHANGELOG.md +45 -0
- package/LICENSE.md +36 -0
- package/README.md +548 -0
- package/build/ArrayBufferFileReader.d.ts +12 -0
- package/build/ArrayBufferFileReader.js +27 -0
- package/build/ArrayFileReader.d.ts +11 -0
- package/build/ArrayFileReader.js +30 -0
- package/build/BlobFileReader.d.ts +12 -0
- package/build/BlobFileReader.js +47 -0
- package/build/ByteArrayUtils.d.ts +9 -0
- package/build/ByteArrayUtils.js +46 -0
- package/build/ChunkedFileData.d.ts +28 -0
- package/build/ChunkedFileData.js +171 -0
- package/build/DecodedString.d.ts +6 -0
- package/build/DecodedString.js +2 -0
- package/build/FLACTagContents.d.ts +19 -0
- package/build/FLACTagContents.js +54 -0
- package/build/FLACTagReader.d.ts +103 -0
- package/build/FLACTagReader.js +320 -0
- package/build/ID3v1TagReader.d.ts +10 -0
- package/build/ID3v1TagReader.js +176 -0
- package/build/ID3v2FrameReader.d.ts +25 -0
- package/build/ID3v2FrameReader.js +582 -0
- package/build/ID3v2TagContents.d.ts +82 -0
- package/build/ID3v2TagContents.js +318 -0
- package/build/ID3v2TagReader.d.ts +13 -0
- package/build/ID3v2TagReader.js +118 -0
- package/build/MP4TagContents.d.ts +17 -0
- package/build/MP4TagContents.js +52 -0
- package/build/MP4TagReader.d.ts +19 -0
- package/build/MP4TagReader.js +291 -0
- package/build/MediaFileReader.d.ts +46 -0
- package/build/MediaFileReader.js +168 -0
- package/build/MediaTagReader.d.ts +18 -0
- package/build/MediaTagReader.js +76 -0
- package/build/NodeFileReader.d.ts +12 -0
- package/build/NodeFileReader.js +103 -0
- package/build/ReactNativeFileReader.d.ts +12 -0
- package/build/ReactNativeFileReader.js +48 -0
- package/build/StringUtils.d.ts +7 -0
- package/build/StringUtils.js +102 -0
- package/build/XhrFileReader.d.ts +41 -0
- package/build/XhrFileReader.js +238 -0
- package/build/jsmediatags.d.ts +45 -0
- package/build/jsmediatags.js +219 -0
- package/build/registerNodeFileReaders.d.ts +5 -0
- package/build/registerNodeFileReaders.js +19 -0
- package/build/registerNodeFileReaders.noop.d.ts +2 -0
- package/build/registerNodeFileReaders.noop.js +3 -0
- package/build/types.d.ts +77 -0
- package/build/types.js +2 -0
- package/dist/jsmediatags.min.js +2 -0
- package/package.json +110 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const MediaFileReader = require("./MediaFileReader");
|
|
3
|
+
const XhrFileReader = require("./XhrFileReader");
|
|
4
|
+
const BlobFileReader = require("./BlobFileReader");
|
|
5
|
+
const ArrayFileReader = require("./ArrayFileReader");
|
|
6
|
+
const MediaTagReader = require("./MediaTagReader");
|
|
7
|
+
const ID3v1TagReader = require("./ID3v1TagReader");
|
|
8
|
+
const ID3v2TagReader = require("./ID3v2TagReader");
|
|
9
|
+
const MP4TagReader = require("./MP4TagReader");
|
|
10
|
+
const FLACTagReader = require("./FLACTagReader");
|
|
11
|
+
const mediaFileReaders = [];
|
|
12
|
+
const mediaTagReaders = [];
|
|
13
|
+
function read(location, callbacks) {
|
|
14
|
+
if (callbacks === undefined) {
|
|
15
|
+
return new Reader(location).read();
|
|
16
|
+
}
|
|
17
|
+
new Reader(location).read(callbacks);
|
|
18
|
+
}
|
|
19
|
+
function readAsync(location) {
|
|
20
|
+
return new Reader(location).read();
|
|
21
|
+
}
|
|
22
|
+
function isRangeValid(range, fileSize) {
|
|
23
|
+
const invalidPositiveRange = range.offset >= 0 && range.offset + range.length >= fileSize;
|
|
24
|
+
const invalidNegativeRange = range.offset < 0 &&
|
|
25
|
+
(-range.offset > fileSize || range.offset + range.length > 0);
|
|
26
|
+
return !(invalidPositiveRange || invalidNegativeRange);
|
|
27
|
+
}
|
|
28
|
+
class Reader {
|
|
29
|
+
constructor(file) {
|
|
30
|
+
this._file = file;
|
|
31
|
+
}
|
|
32
|
+
setTagsToRead(tagsToRead) {
|
|
33
|
+
this._tagsToRead = tagsToRead;
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
setFileReader(fileReader) {
|
|
37
|
+
this._fileReader = fileReader;
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
setTagReader(tagReader) {
|
|
41
|
+
this._tagReader = tagReader;
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
read(callbacks) {
|
|
45
|
+
if (callbacks === undefined) {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
this.read({ onSuccess: resolve, onError: reject });
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const FileReader = this._getFileReader();
|
|
51
|
+
const fileReader = new FileReader(this._file);
|
|
52
|
+
const self = this;
|
|
53
|
+
fileReader.init({
|
|
54
|
+
onSuccess: function () {
|
|
55
|
+
self._getTagReader(fileReader, {
|
|
56
|
+
onSuccess: function (TagReader) {
|
|
57
|
+
var _a;
|
|
58
|
+
new TagReader(fileReader)
|
|
59
|
+
.setTagsToRead((_a = self._tagsToRead) !== null && _a !== void 0 ? _a : null)
|
|
60
|
+
.read(callbacks);
|
|
61
|
+
},
|
|
62
|
+
onError: callbacks.onError,
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
onError: callbacks.onError,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
readAsync() {
|
|
69
|
+
return this.read();
|
|
70
|
+
}
|
|
71
|
+
_getFileReader() {
|
|
72
|
+
if (this._fileReader !== undefined) {
|
|
73
|
+
return this._fileReader;
|
|
74
|
+
}
|
|
75
|
+
return this._findFileReader();
|
|
76
|
+
}
|
|
77
|
+
_findFileReader() {
|
|
78
|
+
for (let i = 0; i < mediaFileReaders.length; i++) {
|
|
79
|
+
if (mediaFileReaders[i].canReadFile(this._file)) {
|
|
80
|
+
return mediaFileReaders[i];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
throw new Error("No suitable file reader found for " + String(this._file));
|
|
84
|
+
}
|
|
85
|
+
_getTagReader(fileReader, callbacks) {
|
|
86
|
+
if (this._tagReader !== undefined) {
|
|
87
|
+
const tagReader = this._tagReader;
|
|
88
|
+
setTimeout(function () {
|
|
89
|
+
callbacks.onSuccess(tagReader);
|
|
90
|
+
}, 1);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
this._findTagReader(fileReader, callbacks);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
_findTagReader(fileReader, callbacks) {
|
|
97
|
+
const tagReadersAtFileStart = [];
|
|
98
|
+
const tagReadersAtFileEnd = [];
|
|
99
|
+
const fileSize = fileReader.getSize();
|
|
100
|
+
for (let i = 0; i < mediaTagReaders.length; i++) {
|
|
101
|
+
const range = mediaTagReaders[i].getTagIdentifierByteRange();
|
|
102
|
+
if (!isRangeValid(range, fileSize)) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if ((range.offset >= 0 && range.offset < fileSize / 2) ||
|
|
106
|
+
(range.offset < 0 && range.offset < -fileSize / 2)) {
|
|
107
|
+
tagReadersAtFileStart.push(mediaTagReaders[i]);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
tagReadersAtFileEnd.push(mediaTagReaders[i]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
let tagsLoaded = false;
|
|
114
|
+
const loadTagIdentifiersCallbacks = {
|
|
115
|
+
onSuccess: function () {
|
|
116
|
+
if (!tagsLoaded) {
|
|
117
|
+
tagsLoaded = true;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
for (let i = 0; i < mediaTagReaders.length; i++) {
|
|
121
|
+
const range = mediaTagReaders[i].getTagIdentifierByteRange();
|
|
122
|
+
if (!isRangeValid(range, fileSize)) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
let tagIndentifier;
|
|
126
|
+
try {
|
|
127
|
+
tagIndentifier = fileReader.getBytesAt(range.offset >= 0 ? range.offset : range.offset + fileSize, range.length);
|
|
128
|
+
}
|
|
129
|
+
catch (ex) {
|
|
130
|
+
const message = ex instanceof Error ? ex.message : String(ex);
|
|
131
|
+
if (callbacks.onError) {
|
|
132
|
+
callbacks.onError({
|
|
133
|
+
type: "fileReader",
|
|
134
|
+
info: message,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (mediaTagReaders[i].canReadTagFormat(tagIndentifier)) {
|
|
140
|
+
callbacks.onSuccess(mediaTagReaders[i]);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (callbacks.onError) {
|
|
145
|
+
callbacks.onError({
|
|
146
|
+
type: "tagFormat",
|
|
147
|
+
info: "No suitable tag reader found",
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
onError: callbacks.onError,
|
|
152
|
+
};
|
|
153
|
+
this._loadTagIdentifierRanges(fileReader, tagReadersAtFileStart, loadTagIdentifiersCallbacks);
|
|
154
|
+
this._loadTagIdentifierRanges(fileReader, tagReadersAtFileEnd, loadTagIdentifiersCallbacks);
|
|
155
|
+
}
|
|
156
|
+
_loadTagIdentifierRanges(fileReader, tagReaders, callbacks) {
|
|
157
|
+
if (tagReaders.length === 0) {
|
|
158
|
+
setTimeout(callbacks.onSuccess, 1);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const tagIdentifierRange = [Number.MAX_VALUE, 0];
|
|
162
|
+
const fileSize = fileReader.getSize();
|
|
163
|
+
for (let i = 0; i < tagReaders.length; i++) {
|
|
164
|
+
const range = tagReaders[i].getTagIdentifierByteRange();
|
|
165
|
+
const start = range.offset >= 0 ? range.offset : range.offset + fileSize;
|
|
166
|
+
const end = start + range.length - 1;
|
|
167
|
+
tagIdentifierRange[0] = Math.min(start, tagIdentifierRange[0]);
|
|
168
|
+
tagIdentifierRange[1] = Math.max(end, tagIdentifierRange[1]);
|
|
169
|
+
}
|
|
170
|
+
fileReader.loadRange(tagIdentifierRange, callbacks);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
class Config {
|
|
174
|
+
static addFileReader(fileReader) {
|
|
175
|
+
mediaFileReaders.push(fileReader);
|
|
176
|
+
return Config;
|
|
177
|
+
}
|
|
178
|
+
static addTagReader(tagReader) {
|
|
179
|
+
mediaTagReaders.push(tagReader);
|
|
180
|
+
return Config;
|
|
181
|
+
}
|
|
182
|
+
static removeTagReader(tagReader) {
|
|
183
|
+
const tagReaderIx = mediaTagReaders.indexOf(tagReader);
|
|
184
|
+
if (tagReaderIx >= 0) {
|
|
185
|
+
mediaTagReaders.splice(tagReaderIx, 1);
|
|
186
|
+
}
|
|
187
|
+
return Config;
|
|
188
|
+
}
|
|
189
|
+
static EXPERIMENTAL_avoidHeadRequests() {
|
|
190
|
+
XhrFileReader.setConfig({
|
|
191
|
+
avoidHeadRequests: true,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
static setDisallowedXhrHeaders(disallowedXhrHeaders) {
|
|
195
|
+
XhrFileReader.setConfig({
|
|
196
|
+
disallowedXhrHeaders: disallowedXhrHeaders,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
static setXhrTimeoutInSec(timeoutInSec) {
|
|
200
|
+
XhrFileReader.setConfig({
|
|
201
|
+
timeoutInSec: timeoutInSec,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
Config.addFileReader(XhrFileReader)
|
|
206
|
+
.addFileReader(BlobFileReader)
|
|
207
|
+
.addFileReader(ArrayFileReader)
|
|
208
|
+
.addTagReader(ID3v2TagReader)
|
|
209
|
+
.addTagReader(ID3v1TagReader)
|
|
210
|
+
.addTagReader(MP4TagReader)
|
|
211
|
+
.addTagReader(FLACTagReader);
|
|
212
|
+
const registerNodeFileReaders = require("./registerNodeFileReaders");
|
|
213
|
+
registerNodeFileReaders(Config);
|
|
214
|
+
module.exports = {
|
|
215
|
+
read: read,
|
|
216
|
+
readAsync: readAsync,
|
|
217
|
+
Reader: Reader,
|
|
218
|
+
Config: Config,
|
|
219
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
function registerNodeFileReaders(Config) {
|
|
3
|
+
const nodeProcess = typeof process !== "undefined"
|
|
4
|
+
? process
|
|
5
|
+
: undefined;
|
|
6
|
+
if (!nodeProcess || nodeProcess.browser) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (typeof navigator !== "undefined" &&
|
|
10
|
+
navigator.product === "ReactNative") {
|
|
11
|
+
const ReactNativeFileReader = require("./ReactNativeFileReader");
|
|
12
|
+
Config.addFileReader(ReactNativeFileReader);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
const NodeFileReader = require("./NodeFileReader");
|
|
16
|
+
Config.addFileReader(NodeFileReader);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
module.exports = registerNodeFileReaders;
|
package/build/types.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type MediaFileReader from "./MediaFileReader";
|
|
2
|
+
export type CallbackType<T = unknown> = {
|
|
3
|
+
onSuccess: (data: T) => void;
|
|
4
|
+
onError?: (error: Record<string, unknown>) => void;
|
|
5
|
+
};
|
|
6
|
+
export type LoadCallbackType = {
|
|
7
|
+
onSuccess: () => void;
|
|
8
|
+
onError?: (error: Record<string, unknown>) => void;
|
|
9
|
+
};
|
|
10
|
+
export type CharsetType = "utf-16" | "utf-16le" | "utf-16be" | "utf-8" | "iso-8859-1";
|
|
11
|
+
export type ByteRange = {
|
|
12
|
+
offset: number;
|
|
13
|
+
length: number;
|
|
14
|
+
};
|
|
15
|
+
export type DataType = Array<number> | Uint8Array | string;
|
|
16
|
+
export type ChunkType = {
|
|
17
|
+
offset: number;
|
|
18
|
+
data: DataType;
|
|
19
|
+
};
|
|
20
|
+
export type Byte = number;
|
|
21
|
+
export type ByteArray = Byte[];
|
|
22
|
+
export type FrameReaderSignature = (offset: number, length: number, data: MediaFileReader, flags: Record<string, unknown> | null, id3header?: TagHeader) => unknown;
|
|
23
|
+
export type TagFrames = {
|
|
24
|
+
[key: string]: TagFrame | TagFrame[];
|
|
25
|
+
};
|
|
26
|
+
export type TagFrame = {
|
|
27
|
+
id: string;
|
|
28
|
+
size: number;
|
|
29
|
+
description: string;
|
|
30
|
+
data: unknown;
|
|
31
|
+
};
|
|
32
|
+
export type TagFrameHeader = {
|
|
33
|
+
id: string;
|
|
34
|
+
size: number;
|
|
35
|
+
headerSize: number;
|
|
36
|
+
flags: TagFrameFlags | null | undefined;
|
|
37
|
+
};
|
|
38
|
+
export type TagFrameFlags = {
|
|
39
|
+
message: {
|
|
40
|
+
tag_alter_preservation: boolean;
|
|
41
|
+
file_alter_preservation: boolean;
|
|
42
|
+
read_only: boolean;
|
|
43
|
+
};
|
|
44
|
+
format: {
|
|
45
|
+
grouping_identity: boolean;
|
|
46
|
+
compression: boolean;
|
|
47
|
+
encryption: boolean;
|
|
48
|
+
unsynchronisation: boolean;
|
|
49
|
+
data_length_indicator: boolean;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export type TagHeader = {
|
|
53
|
+
version: string;
|
|
54
|
+
major: number;
|
|
55
|
+
revision: number;
|
|
56
|
+
flags: TagHeaderFlags;
|
|
57
|
+
size: number;
|
|
58
|
+
};
|
|
59
|
+
export type TagHeaderFlags = {
|
|
60
|
+
unsynchronisation: boolean;
|
|
61
|
+
extended_header: boolean;
|
|
62
|
+
experimental_indicator: boolean;
|
|
63
|
+
footer_present: boolean;
|
|
64
|
+
};
|
|
65
|
+
export type TagType = {
|
|
66
|
+
type: string;
|
|
67
|
+
tags: {
|
|
68
|
+
[key: string]: FrameType | ShortcutType;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
export type FrameType = {
|
|
72
|
+
id: string;
|
|
73
|
+
description: string;
|
|
74
|
+
data: unknown;
|
|
75
|
+
};
|
|
76
|
+
type ShortcutType = unknown;
|
|
77
|
+
export {};
|
package/build/types.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var jsmediatags=(()=>{var Ge=Object.defineProperty;var ae=Object.getOwnPropertySymbols;var je=Object.prototype.hasOwnProperty,Ye=Object.prototype.propertyIsEnumerable;var oe=(s,e,t)=>e in s?Ge(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t,se=(s,e)=>{for(var t in e||(e={}))je.call(e,t)&&oe(s,t,e[t]);if(ae)for(var t of ae(e))Ye.call(e,t)&&oe(s,t,e[t]);return s};var m=(s,e)=>()=>(e||s((e={exports:{}}).exports,e),e.exports);var H=m((vt,ue)=>{"use strict";var D=class{constructor(e,t){this._value=e,this.bytesReadCount=t,this.length=e.length}toString(){return this._value}},Ve={readUTF16String:function(s,e,t){let r=0,n=1,i=0;t=Math.min(t||s.length,s.length),s[0]==254&&s[1]==255?(e=!0,r=2):s[0]==255&&s[1]==254&&(e=!1,r=2),e&&(n=0,i=1);let a=[];for(let o=0;r<t;o++){let u=s[r+n],c=s[r+i],l=(u<<8)+c;if(r+=2,l==0)break;if(u<216||u>=224)a[o]=String.fromCharCode(l);else{let d=s[r+n],g=s[r+i],y=(d<<8)+g;r+=2,a[o]=String.fromCharCode(l,y)}}return new D(a.join(""),r)},readUTF8String:function(s,e){let t=0;e=Math.min(e||s.length,s.length),s[0]==239&&s[1]==187&&s[2]==191&&(t=3);let r=[];for(let n=0;t<e;n++){let i=s[t++];if(i==0)break;if(i<128)r[n]=String.fromCharCode(i);else if(i>=194&&i<224){let a=s[t++];r[n]=String.fromCharCode(((i&31)<<6)+(a&63))}else if(i>=224&&i<240){let a=s[t++],o=s[t++];r[n]=String.fromCharCode(((i&255)<<12)+((a&63)<<6)+(o&63))}else if(i>=240&&i<245){let a=s[t++],o=s[t++],u=s[t++],c=((i&7)<<18)+((a&63)<<12)+((o&63)<<6)+(u&63)-65536;r[n]=String.fromCharCode((c>>10)+55296,(c&1023)+56320)}}return new D(r.join(""),t)},readNullTerminatedString:function(s,e){let t=[];e=e||s.length;for(var r=0;r<e;){var n=s[r++];if(n==0)break;t[r-1]=String.fromCharCode(n)}return new D(t.join(""),r)}};ue.exports=Ve});var f=m((Mt,ce)=>{"use strict";var U=H(),z=class{constructor(e){this._isInitialized=!1,this._size=0}static canReadFile(e){throw new Error("Must implement canReadFile function")}init(e){let t=this;this._isInitialized?setTimeout(e.onSuccess,1):this._init({onSuccess:function(){t._isInitialized=!0,e.onSuccess()},onError:e.onError})}_init(e){throw new Error("Must implement init function")}loadRange(e,t){throw new Error("Must implement loadRange function")}getSize(){if(!this._isInitialized)throw new Error("init() must be called first.");return this._size}getByteAt(e){throw new Error("Must implement getByteAt function")}getBytesAt(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=this.getByteAt(e+n);return r}isBitSetAt(e,t){return(this.getByteAt(e)&1<<t)!=0}getSByteAt(e){let t=this.getByteAt(e);return t>127?t-256:t}getShortAt(e,t){let r=t?(this.getByteAt(e)<<8)+this.getByteAt(e+1):(this.getByteAt(e+1)<<8)+this.getByteAt(e);return r<0&&(r+=65536),r}getSShortAt(e,t){let r=this.getShortAt(e,t);return r>32767?r-65536:r}getLongAt(e,t){let r=this.getByteAt(e),n=this.getByteAt(e+1),i=this.getByteAt(e+2),a=this.getByteAt(e+3),o=t?(((r<<8)+n<<8)+i<<8)+a:(((a<<8)+i<<8)+n<<8)+r;return o<0&&(o+=4294967296),o}getSLongAt(e,t){let r=this.getLongAt(e,t);return r>2147483647?r-4294967296:r}getInteger24At(e,t){let r=this.getByteAt(e),n=this.getByteAt(e+1),i=this.getByteAt(e+2),a=t?((r<<8)+n<<8)+i:((i<<8)+n<<8)+r;return a<0&&(a+=16777216),a}getStringAt(e,t){let r=[];for(let n=e,i=0;n<e+t;n++,i++)r[i]=String.fromCharCode(this.getByteAt(n));return r.join("")}getStringWithCharsetAt(e,t,r){let n=this.getBytesAt(e,t),i;switch((r||"").toLowerCase()){case"utf-16":case"utf-16le":case"utf-16be":i=U.readUTF16String(n,r==="utf-16be");break;case"utf-8":i=U.readUTF8String(n);break;default:i=U.readNullTerminatedString(n);break}return i}getCharAt(e){return String.fromCharCode(this.getByteAt(e))}getSynchsafeInteger32At(e){let t=this.getByteAt(e),r=this.getByteAt(e+1),n=this.getByteAt(e+2);return this.getByteAt(e+3)&127|(n&127)<<7|(r&127)<<14|(t&127)<<21}};ce.exports=z});var N=m((kt,de)=>{"use strict";function v(s){return s.length}function le(s){return s instanceof Uint8Array}var q=class{static get NOT_FOUND(){return-1}constructor(){this._fileData=[]}addData(e,t){let r=e+v(t)-1,n=this._getChunkRange(e,r);if(n.startIx===-1)this._fileData.splice(n.insertIx||0,0,{offset:e,data:t});else{let i=this._fileData[n.startIx],a=this._fileData[n.endIx],o=e>i.offset,u=r<a.offset+v(a.data)-1,c={offset:Math.min(e,i.offset),data:t};if(o){let l=this._sliceData(i.data,0,e-i.offset);c.data=this._concatData(l,t)}if(u){let l=this._sliceData(c.data,0,a.offset-c.offset);c.data=this._concatData(l,a.data)}this._fileData.splice(n.startIx,n.endIx-n.startIx+1,c)}}_concatData(e,t){if(le(e)&&le(t)){let i=e.constructor,a=new i(e.length+t.length);return a.set(e,0),a.set(t,e.length),a}return Array.isArray(e)&&Array.isArray(t)?e.concat(t):(typeof e=="string"?e:"")+(typeof t=="string"?t:"")}_sliceData(e,t,r){if(typeof e=="string"||Array.isArray(e))return e.slice(t,r);let n=e;return typeof n.subarray=="function"?n.subarray(t,r):n.slice(t,r)}_getChunkRange(e,t){let r=-1,n=-1,i=0;for(let a=0;a<this._fileData.length;a++,i=a){let o=this._fileData[a].offset,u=o+v(this._fileData[a].data);if(t<o-1)break;if(e<=u+1&&t>=o-1){r=a;break}}if(r===-1)return{startIx:-1,endIx:-1,insertIx:i};for(let a=r;a<this._fileData.length;a++){let o=this._fileData[a].offset,u=o+v(this._fileData[a].data);if(t>=o-1&&(n=a),t<=u+1)break}return n===-1&&(n=r),{startIx:r,endIx:n}}hasDataRange(e,t){for(let r=0;r<this._fileData.length;r++){let n=this._fileData[r];if(t<n.offset)return!1;if(e>=n.offset&&t<n.offset+v(n.data))return!0}return!1}getByteAt(e){let t;for(let r=0;r<this._fileData.length;r++){let n=this._fileData[r].offset,i=n+v(this._fileData[r].data)-1;if(e>=n&&e<=i){t=this._fileData[r];break}}if(t){let r=e-t.offset,n=t.data;return typeof n=="string"?n.charCodeAt(r)&255:(Array.isArray(n),n[r])}throw new Error("Offset "+e+" hasn't been loaded yet.")}};de.exports=q});var pe=m((Et,ge)=>{ge.exports={XMLHttpRequest:globalThis.XMLHttpRequest}});var me=m((Dt,Te)=>{"use strict";var Ke=N(),Je=f(),ye=1024,b=class b extends Je{constructor(e){super(),this._url=e,this._fileData=new Ke}static canReadFile(e){return typeof e=="string"&&/^[a-z]+:\/\//i.test(e)}static setConfig(e){for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(b._config[r]=e[r]);let t=b._config.disallowedXhrHeaders;for(let r=0;r<t.length;r++)t[r]=t[r].toLowerCase()}_init(e){b._config.avoidHeadRequests?this._fetchSizeWithGetRequest(e):this._fetchSizeWithHeadRequest(e)}_fetchSizeWithHeadRequest(e){let t=this;this._makeXHRRequest("HEAD",null,{onSuccess:function(r){let n=t._parseContentLength(r);n?(t._size=n,e.onSuccess()):t._fetchSizeWithGetRequest(e)},onError:e.onError})}_fetchSizeWithGetRequest(e){let t=this,r=this._roundRangeToChunkMultiple([0,0]);this._makeXHRRequest("GET",r,{onSuccess:function(n){let i=t._parseContentRange(n),a=t._getXhrResponseContent(n);if(i){if(i.instanceLength==null){t._fetchEntireFile(e);return}t._size=i.instanceLength}else t._size=a.length;t._fileData.addData(0,a),e.onSuccess()},onError:e.onError})}_fetchEntireFile(e){let t=this;this._makeXHRRequest("GET",null,{onSuccess:function(r){let n=t._getXhrResponseContent(r);t._size=n.length,t._fileData.addData(0,n),e.onSuccess()},onError:e.onError})}_getXhrResponseContent(e){return e.responseBody||e.responseText||""}_parseContentLength(e){let t=this._getResponseHeader(e,"Content-Length");return t==null?null:parseInt(t,10)}_parseContentRange(e){let t=this._getResponseHeader(e,"Content-Range");if(t){let r=t.match(/bytes (\d+)-(\d+)\/(?:(\d+)|\*)/i);if(!r)throw new Error("FIXME: Unknown Content-Range syntax: "+t);return{firstBytePosition:parseInt(r[1],10),lastBytePosition:parseInt(r[2],10),instanceLength:r[3]?parseInt(r[3],10):null}}else return null}loadRange(e,t){let r=this;if(r._fileData.hasDataRange(e[0],Math.min(r._size,e[1]))){setTimeout(t.onSuccess,1);return}e=this._roundRangeToChunkMultiple(e),e[1]=Math.min(r._size,e[1]),this._makeXHRRequest("GET",e,{onSuccess:function(n){let i=r._getXhrResponseContent(n);r._fileData.addData(e[0],i),t.onSuccess()},onError:t.onError})}_roundRangeToChunkMultiple(e){let t=e[1]-e[0]+1,r=Math.ceil(t/ye)*ye;return[e[0],e[0]+r-1]}_makeXHRRequest(e,t,r){let n=this._createXHRObject();n.open(e,this._url);let i=function(){n.status===200||n.status===206?r.onSuccess(n):r.onError&&r.onError({type:"xhr",info:"Unexpected HTTP status "+n.status+".",xhr:n})};typeof n.onload!="undefined"?(n.onload=i,n.onerror=function(){r.onError&&r.onError({type:"xhr",info:"Generic XHR error, check xhr object.",xhr:n})}):n.onreadystatechange=function(){n.readyState===4&&i()},b._config.timeoutInSec&&(n.timeout=b._config.timeoutInSec*1e3,n.ontimeout=function(){r.onError&&r.onError({type:"xhr",info:"Timeout after "+n.timeout/1e3+"s. Use jsmediatags.Config.setXhrTimeout to override.",xhr:n})}),n.overrideMimeType("text/plain; charset=x-user-defined"),t&&this._setRequestHeader(n,"Range","bytes="+t[0]+"-"+t[1]),this._setRequestHeader(n,"If-Modified-Since","Sat, 01 Jan 1970 00:00:00 GMT"),n.send(null)}_setRequestHeader(e,t,r){b._config.disallowedXhrHeaders.indexOf(t.toLowerCase())<0&&e.setRequestHeader(t,r)}_hasResponseHeader(e,t){let r=e.getAllResponseHeaders();if(!r)return!1;let n=r.split(`\r
|
|
2
|
+
`),i=[];for(let a=0;a<n.length;a++)i[a]=n[a].split(":")[0].toLowerCase();return i.indexOf(t.toLowerCase())>=0}_getResponseHeader(e,t){return this._hasResponseHeader(e,t)?e.getResponseHeader(t):null}getByteAt(e){return this._fileData.getByteAt(e)&255}_isWebWorker(){return typeof WorkerGlobalScope!="undefined"&&typeof self!="undefined"&&self instanceof WorkerGlobalScope}_createXHRObject(){if(typeof window=="undefined"&&!this._isWebWorker()){let e=pe();return new e.XMLHttpRequest}if(typeof XMLHttpRequest!="undefined")return new XMLHttpRequest;throw new Error("XMLHttpRequest is not supported")}};b._config={avoidHeadRequests:!1,disallowedXhrHeaders:[],timeoutInSec:30};var X=b;Te.exports=X});var fe=m((wt,he)=>{"use strict";var Ze=N(),Qe=f(),W=class extends Qe{constructor(e){super(),this._blob=e,this._fileData=new Ze}static canReadFile(e){return typeof Blob!="undefined"&&e instanceof Blob||typeof File!="undefined"&&e instanceof File}_init(e){this._size=this._blob.size,setTimeout(e.onSuccess,1)}loadRange(e,t){let r=this,i=(this._blob.slice||this._blob.mozSlice||this._blob.webkitSlice).call(this._blob,e[0],e[1]+1),a=new FileReader;a.onloadend=function(){let o=a.result,u=new Uint8Array(o);r._fileData.addData(e[0],u),t.onSuccess()},a.onerror=a.onabort=function(){t.onError&&t.onError({type:"blob",info:a.error})},a.readAsArrayBuffer(i)}getByteAt(e){return this._fileData.getByteAt(e)}};he.exports=W});var j=m((Ft,Re)=>{"use strict";var $e=f(),G=class extends $e{constructor(e){super(),this._array=e,this._size=e.length,this._isInitialized=!0}static canReadFile(e){return Array.isArray(e)||typeof Buffer=="function"&&typeof Buffer.isBuffer=="function"&&Buffer.isBuffer(e)}init(e){setTimeout(e.onSuccess,0)}loadRange(e,t){setTimeout(t.onSuccess,0)}getByteAt(e){if(e>=this._array.length)throw new Error("Offset "+e+" hasn't been loaded yet.");return this._array[e]}};Re.exports=G});var M=m((Bt,be)=>{"use strict";var Lt=f(),Y=class{constructor(e){this._mediaFileReader=e,this._tags=null}static getTagIdentifierByteRange(){throw new Error("Must implement")}static canReadTagFormat(e){throw new Error("Must implement")}setTagsToRead(e){return this._tags=e,this}read(e){if(e===void 0)return new Promise((r,n)=>{this.read({onSuccess:r,onError:n})});let t=this;this._mediaFileReader.init({onSuccess:function(){t._loadData(t._mediaFileReader,{onSuccess:function(){let r;try{r=t._parseData(t._mediaFileReader,t._tags)}catch(n){let i=n;e.onError&&e.onError({type:"parseData",info:i.message});return}e.onSuccess(r)},onError:e.onError})},onError:e.onError})}readAsync(){return this.read()}getShortcuts(){return{}}_loadData(e,t){throw new Error("Must implement _loadData function")}_parseData(e,t){throw new Error("Must implement _parseData function")}_expandShortcutTags(e){if(!e)return null;let t=[],r=this.getShortcuts();for(let n=0,i;i=e[n];n++)t=t.concat(r[i]||[i]);return t}};be.exports=Y});var Se=m((It,Ce)=>{"use strict";var et=M(),xt=f(),V=class extends et{static getTagIdentifierByteRange(){return{offset:-128,length:128}}static canReadTagFormat(e){return String.fromCharCode.apply(String,e.slice(0,3))==="TAG"}_loadData(e,t){let r=e.getSize();e.loadRange([r-128,r-1],t)}_parseData(e,t){let r=e.getSize()-128,n=e.getStringWithCharsetAt(r+3,30).toString(),i=e.getStringWithCharsetAt(r+33,30).toString(),a=e.getStringWithCharsetAt(r+63,30).toString(),o=e.getStringWithCharsetAt(r+93,4).toString(),u=e.getByteAt(r+97+28),c=e.getByteAt(r+97+29),l,d;u==0&&c!=0?(l="1.1",d=e.getStringWithCharsetAt(r+97,28).toString()):(l="1.0",d=e.getStringWithCharsetAt(r+97,30).toString(),c=0);let g=e.getByteAt(r+97+30),y=g<255?tt[g]:"";return{type:"ID3",version:l,tags:se({title:n,artist:i,album:a,year:o,comment:d,genre:y},c?{track:c}:{})}}},tt=["Blues","Classic Rock","Country","Dance","Disco","Funk","Grunge","Hip-Hop","Jazz","Metal","New Age","Oldies","Other","Pop","R&B","Rap","Reggae","Rock","Techno","Industrial","Alternative","Ska","Death Metal","Pranks","Soundtrack","Euro-Techno","Ambient","Trip-Hop","Vocal","Jazz+Funk","Fusion","Trance","Classical","Instrumental","Acid","House","Game","Sound Clip","Gospel","Noise","AlternRock","Bass","Soul","Punk","Space","Meditative","Instrumental Pop","Instrumental Rock","Ethnic","Gothic","Darkwave","Techno-Industrial","Electronic","Pop-Folk","Eurodance","Dream","Southern Rock","Comedy","Cult","Gangsta","Top 40","Christian Rap","Pop/Funk","Jungle","Native American","Cabaret","New Wave","Psychadelic","Rave","Showtunes","Trailer","Lo-Fi","Tribal","Acid Punk","Acid Jazz","Polka","Retro","Musical","Rock & Roll","Hard Rock","Folk","Folk-Rock","National Folk","Swing","Fast Fusion","Bebob","Latin","Revival","Celtic","Bluegrass","Avantgarde","Gothic Rock","Progressive Rock","Psychedelic Rock","Symphonic Rock","Slow Rock","Big Band","Chorus","Easy Listening","Acoustic","Humour","Speech","Chanson","Opera","Chamber Music","Sonata","Symphony","Booty Bass","Primus","Porn Groove","Satire","Slow Jam","Club","Tango","Samba","Folklore","Ballad","Power Ballad","Rhythmic Soul","Freestyle","Duet","Punk Rock","Drum Solo","Acapella","Euro-House","Dance Hall"];Ce.exports=V});var Me=m((Ht,ve)=>{"use strict";var Pt=f(),L=H(),rt=j(),Ae={BUF:"Recommended buffer size",CNT:"Play counter",COM:"Comments",CRA:"Audio encryption",CRM:"Encrypted meta frame",ETC:"Event timing codes",EQU:"Equalization",GEO:"General encapsulated object",IPL:"Involved people list",LNK:"Linked information",MCI:"Music CD Identifier",MLL:"MPEG location lookup table",PIC:"Attached picture",POP:"Popularimeter",REV:"Reverb",RVA:"Relative volume adjustment",SLT:"Synchronized lyric/text",STC:"Synced tempo codes",TAL:"Album/Movie/Show title",TBP:"BPM (Beats Per Minute)",TCM:"Composer",TCO:"Content type",TCR:"Copyright message",TDA:"Date",TDY:"Playlist delay",TEN:"Encoded by",TFT:"File type",TIM:"Time",TKE:"Initial key",TLA:"Language(s)",TLE:"Length",TMT:"Media type",TOA:"Original artist(s)/performer(s)",TOF:"Original filename",TOL:"Original Lyricist(s)/text writer(s)",TOR:"Original release year",TOT:"Original album/Movie/Show title",TP1:"Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group",TP2:"Band/Orchestra/Accompaniment",TP3:"Conductor/Performer refinement",TP4:"Interpreted, remixed, or otherwise modified by",TPA:"Part of a set",TPB:"Publisher",TRC:"ISRC (International Standard Recording Code)",TRD:"Recording dates",TRK:"Track number/Position in set",TSI:"Size",TSS:"Software/hardware and settings used for encoding",TT1:"Content group description",TT2:"Title/Songname/Content description",TT3:"Subtitle/Description refinement",TXT:"Lyricist/text writer",TXX:"User defined text information frame",TYE:"Year",UFI:"Unique file identifier",ULT:"Unsychronized lyric/text transcription",WAF:"Official audio file webpage",WAR:"Official artist/performer webpage",WAS:"Official audio source webpage",WCM:"Commercial information",WCP:"Copyright/Legal information",WPB:"Publishers official webpage",WXX:"User defined URL link frame",AENC:"Audio encryption",APIC:"Attached picture",ASPI:"Audio seek point index",CHAP:"Chapter",CTOC:"Table of contents",COMM:"Comments",COMR:"Commercial frame",ENCR:"Encryption method registration",EQU2:"Equalisation (2)",EQUA:"Equalization",ETCO:"Event timing codes",GEOB:"General encapsulated object",GRID:"Group identification registration",IPLS:"Involved people list",LINK:"Linked information",MCDI:"Music CD identifier",MLLT:"MPEG location lookup table",OWNE:"Ownership frame",PRIV:"Private frame",PCNT:"Play counter",POPM:"Popularimeter",POSS:"Position synchronisation frame",RBUF:"Recommended buffer size",RVA2:"Relative volume adjustment (2)",RVAD:"Relative volume adjustment",RVRB:"Reverb",SEEK:"Seek frame",SYLT:"Synchronized lyric/text",SYTC:"Synchronized tempo codes",TALB:"Album/Movie/Show title",TBPM:"BPM (beats per minute)",TCOM:"Composer",TCON:"Content type",TCOP:"Copyright message",TDAT:"Date",TDLY:"Playlist delay",TDRC:"Recording time",TDRL:"Release time",TDTG:"Tagging time",TENC:"Encoded by",TEXT:"Lyricist/Text writer",TFLT:"File type",TIME:"Time",TIPL:"Involved people list",TIT1:"Content group description",TIT2:"Title/songname/content description",TIT3:"Subtitle/Description refinement",TKEY:"Initial key",TLAN:"Language(s)",TLEN:"Length",TMCL:"Musician credits list",TMED:"Media type",TMOO:"Mood",TOAL:"Original album/movie/show title",TOFN:"Original filename",TOLY:"Original lyricist(s)/text writer(s)",TOPE:"Original artist(s)/performer(s)",TORY:"Original release year",TOWN:"File owner/licensee",TPE1:"Lead performer(s)/Soloist(s)",TPE2:"Band/orchestra/accompaniment",TPE3:"Conductor/performer refinement",TPE4:"Interpreted, remixed, or otherwise modified by",TPOS:"Part of a set",TPRO:"Produced notice",TPUB:"Publisher",TRCK:"Track number/Position in set",TRDA:"Recording dates",TRSN:"Internet radio station name",TRSO:"Internet radio station owner",TSOA:"Album sort order",TSOP:"Performer sort order",TSOT:"Title sort order",TSIZ:"Size",TSRC:"ISRC (international standard recording code)",TSSE:"Software/Hardware and settings used for encoding",TSST:"Set subtitle",TYER:"Year",TXXX:"User defined text information frame",UFID:"Unique file identifier",USER:"Terms of use",USLT:"Unsychronized lyric/text transcription",WCOM:"Commercial information",WCOP:"Copyright/Legal information",WOAF:"Official audio file webpage",WOAR:"Official artist/performer webpage",WOAS:"Official audio source webpage",WORS:"Official internet radio station homepage",WPAY:"Payment",WPUB:"Publishers official webpage",WXXX:"User defined URL link frame"},w=class s{static getFrameReaderFunction(e){var t,r,n;return e in p?(t=p[e])!=null?t:null:e[0]==="T"?(r=p["T*"])!=null?r:null:e[0]==="W"&&(n=p["W*"])!=null?n:null}static readFrames(e,t,r,n,i){let a={};for(var o=this._getFrameHeaderSize(n);e<t-o;){var u=this._readFrameHeader(r,e,n),c=u.id;if(!c)break;var l=u.flags,d=u.size,g=e+u.headerSize,y=r;if(e+=u.headerSize+u.size,!(i&&i.indexOf(c)===-1)){if(c==="MP3e"||c==="\0MP3"||c==="\0\0MP"||c===" MP3")break;l&&l.format.unsynchronisation&&!n.flags.unsynchronisation&&(y=this.getUnsyncFileReader(y,g,d),g=0,d=y.getSize()),l&&l.format.data_length_indicator&&(g+=4,d-=4);var h=s.getFrameReaderFunction(c),T=h?h.apply(this,[g,d,y,l!=null?l:null,n]):null,C=this._getFrameDescription(c),E={id:c,size:d,description:C,data:T};if(c in a){let S=a[c];S&&!Array.isArray(S)&&S.id&&(a[c]=[S]),a[c].push(E)}else a[c]=E}}return a}static _getFrameHeaderSize(e){var t=e.major;return t==2?6:t==3||t==4?10:0}static _readFrameHeader(e,t,r){var n=r.major,i=null,a=this._getFrameHeaderSize(r);let o="",u=0;switch(n){case 2:o=e.getStringAt(t,3),u=e.getInteger24At(t+3,!0);break;case 3:o=e.getStringAt(t,4),u=e.getLongAt(t+4,!0);break;case 4:o=e.getStringAt(t,4),u=e.getSynchsafeInteger32At(t+4);break}return(o=="\0\0\0"||o=="\0\0\0\0")&&(o=""),o&&n>2&&(i=this._readFrameFlags(e,t+8)),{id:o||"",size:u||0,headerSize:a||0,flags:i}}static _readFrameFlags(e,t){return{message:{tag_alter_preservation:e.isBitSetAt(t,6),file_alter_preservation:e.isBitSetAt(t,5),read_only:e.isBitSetAt(t,4)},format:{grouping_identity:e.isBitSetAt(t+1,7),compression:e.isBitSetAt(t+1,3),encryption:e.isBitSetAt(t+1,2),unsynchronisation:e.isBitSetAt(t+1,1),data_length_indicator:e.isBitSetAt(t+1,0)}}}static _getFrameDescription(e){return e in Ae?Ae[e]:"Unknown"}static getUnsyncFileReader(e,t,r){for(var n=e.getBytesAt(t,r),i=0;i<n.length-1;i++)n[i]===255&&n[i+1]===0&&n.splice(i+1,1);return new rt(n)}},p={};p.APIC=function(e,t,r,n,i){var a=e,o=A(r.getByteAt(e));let u;switch(i&&i.major){case 2:u=r.getStringAt(e+1,3),e+=4;break;case 3:case 4:{let g=r.getStringWithCharsetAt(e+1,t-1);u=g.toString(),e+=1+g.bytesReadCount;break}default:throw new Error("Couldn't read ID3v2 major version.")}var c=r.getByteAt(e),l=nt[c],d=r.getStringWithCharsetAt(e+1,t-(e-a)-1,o);return e+=1+d.bytesReadCount,{format:u,type:l,description:d.toString(),data:r.getBytesAt(e,a+t-e)}};p.CHAP=function(e,t,r,n,i){var a=e,o={},u=L.readNullTerminatedString(r.getBytesAt(e,t));o.id=u.toString(),e+=u.bytesReadCount,o.startTime=r.getLongAt(e,!0),e+=4,o.endTime=r.getLongAt(e,!0),e+=4,o.startOffset=r.getLongAt(e,!0),e+=4,o.endOffset=r.getLongAt(e,!0),e+=4;var c=t-(e-a);return o.subFrames=w.readFrames(e,e+c,r,i,void 0),o};p.CTOC=function(e,t,r,n,i){var a=e,o={childElementIds:[]},u=L.readNullTerminatedString(r.getBytesAt(e,t));o.id=u.toString(),e+=u.bytesReadCount,o.topLevel=r.isBitSetAt(e,1),o.ordered=r.isBitSetAt(e,0),e++,o.entryCount=r.getByteAt(e),e++;let c=o.entryCount;for(var l=0;l<c;l++){var d=L.readNullTerminatedString(r.getBytesAt(e,t-(e-a)));o.childElementIds.push(d.toString()),e+=d.bytesReadCount}var g=t-(e-a);return o.subFrames=w.readFrames(e,e+g,r,i,void 0),o};p.COMM=function(e,t,r,n,i){var a=e,o=A(r.getByteAt(e)),u=r.getStringAt(e+1,3),c=r.getStringWithCharsetAt(e+4,t-4,o);e+=4+c.bytesReadCount;var l=r.getStringWithCharsetAt(e,a+t-e,o);return{language:u,short_description:c.toString(),text:l.toString()}};p.COM=p.COMM;p.PIC=function(s,e,t,r,n){return p.APIC(s,e,t,r,n)};p.PCNT=function(e,t,r,n,i){return r.getLongAt(e,!1)};p.CNT=p.PCNT;p.SYLT=function(e,t,r,n,i){var a=e,o=["other","lyrics","transcription","movement","events","chord","trivia"],u=["unset","frames","milliseconds"],c=A(r.getByteAt(e));e+=1;var l=r.getStringAt(e,3);e+=3;var d=u[r.getByteAt(e)];e+=1;var g=o[r.getByteAt(e)];e+=1;var y=r.getStringWithCharsetAt(e,t+a-e,c);e+=y.bytesReadCount;for(var h=[];e<t+a;){let T=r.getStringWithCharsetAt(e,t+a-e,c);e+=T.bytesReadCount,h.push({text:T.toString(),timeStamp:r.getLongAt(e,!0)}),e+=4}return{language:l,timeStampFormat:d,contentType:g,descriptor:y.toString(),synchronisedText:h}};p["T*"]=function(e,t,r,n,i){var a=A(r.getByteAt(e));return r.getStringWithCharsetAt(e+1,t-1,a).toString()};p.TXXX=function(e,t,r,n,i){var a=A(r.getByteAt(e));return _e(e,t,r,a)};p.WXXX=function(e,t,r,n,i){if(t===0)return null;var a=A(r.getByteAt(e));return _e(e,t,r,a)};p["W*"]=function(e,t,r,n,i){return t===0?null:r.getStringWithCharsetAt(e,t,"iso-8859-1").toString()};p.TCON=function(e,t,r,n){var a=p["T*"].apply(this,arguments);return a.replace(/^\(\d+\)/,"")};p.TCO=p.TCON;p.USLT=function(e,t,r,n,i){var a=e,o=A(r.getByteAt(e)),u=r.getStringAt(e+1,3),c=r.getStringWithCharsetAt(e+4,t-4,o);e+=4+c.bytesReadCount;var l=r.getStringWithCharsetAt(e,a+t-e,o);return{language:u,descriptor:c.toString(),lyrics:l.toString()}};p.ULT=p.USLT;p.UFID=function(e,t,r,n,i){var a=L.readNullTerminatedString(r.getBytesAt(e,t));e+=a.bytesReadCount;var o=r.getBytesAt(e,t-a.bytesReadCount);return{ownerIdentifier:a.toString(),identifier:o}};function A(s){var e;switch(s){case 0:e="iso-8859-1";break;case 1:e="utf-16";break;case 2:e="utf-16be";break;case 3:e="utf-8";break;default:e="iso-8859-1"}return e}function _e(s,e,t,r){var n=t.getStringWithCharsetAt(s+1,e-1,r),i=t.getStringWithCharsetAt(s+1+n.bytesReadCount,e-1-n.bytesReadCount,r);return{user_description:n.toString(),data:i.toString()}}var nt=["Other","32x32 pixels 'file icon' (PNG only)","Other file icon","Cover (front)","Cover (back)","Leaflet page","Media (e.g. label side of CD)","Lead artist/lead performer/soloist","Artist/performer","Conductor","Band/Orchestra","Composer","Lyricist/text writer","Recording Location","During recording","During performance","Movie/video screen capture","A bright coloured fish","Illustration","Band/artist logotype","Publisher/Studio logotype"];ve.exports=w});var we=m((zt,De)=>{"use strict";var it=M(),Ut=f(),ke=Me(),Ee=10,K=class extends it{static getTagIdentifierByteRange(){return{offset:0,length:Ee}}static canReadTagFormat(e){return String.fromCharCode.apply(String,e.slice(0,3))==="ID3"}_loadData(e,t){e.loadRange([6,9],{onSuccess:function(){e.loadRange([0,Ee+e.getSynchsafeInteger32At(6)-1],t)},onError:t.onError})}_parseData(e,t){let r=0,n=e.getByteAt(r+3);if(n>4)return{type:"ID3",tags:{version:">2.4"}};let i=e.getByteAt(r+4),a=e.isBitSetAt(r+5,7),o=e.isBitSetAt(r+5,6),u=e.isBitSetAt(r+5,5),c=e.getSynchsafeInteger32At(r+6);if(r+=10,o)if(n===4){let T=e.getSynchsafeInteger32At(r);r+=T}else{let T=e.getLongAt(r,!0);r+=T+4}let l={type:"ID3",version:"2."+n+"."+i,major:n,revision:i,flags:{unsynchronisation:a,extended_header:o,experimental_indicator:u,footer_present:!1},size:c,tags:{}},d;t&&(d=this._expandShortcutTags(t));let g=c+10,y=e;l.flags.unsynchronisation&&(y=ke.getUnsyncFileReader(y,r,c),r=0,g=y.getSize());let h=ke.readFrames(r,g,y,l,d!=null?d:void 0);for(let T in B)if(B.hasOwnProperty(T)){let C=this._getFrameData(h,B[T]);C&&(l.tags[T]=C)}for(let T in h)h.hasOwnProperty(T)&&(l.tags[T]=h[T]);return l}_getFrameData(e,t){let r;for(let n=0,i;i=t[n];n++)if(i in e)return r=e[i],Array.isArray(r)&&(r=r[0]),r.data}getShortcuts(){return B}},B={title:["TIT2","TT2"],artist:["TPE1","TP1"],album:["TALB","TAL"],year:["TYER","TYE"],comment:["COMM","COM"],track:["TRCK","TRK"],genre:["TCON","TCO"],picture:["APIC","PIC"],lyrics:["USLT","ULT"]};De.exports=K});var Le=m((Nt,Fe)=>{"use strict";var at=M(),qt=f(),J=class extends at{static getTagIdentifierByteRange(){return{offset:0,length:16}}static canReadTagFormat(e){var t=String.fromCharCode.apply(String,e.slice(4,8));return t==="ftyp"}_loadData(e,t){var r=this;e.loadRange([0,16],{onSuccess:function(){r._loadAtom(e,0,"",t)},onError:t.onError})}_loadAtom(e,t,r,n){if(t>=e.getSize()){n.onSuccess();return}var i=this,a=e.getLongAt(t,!0);if(a==0||isNaN(a)){n.onSuccess();return}var o=e.getStringAt(t+4,4);if(this._isContainerAtom(o)){o=="meta"&&(t+=4);var u=(r?r+".":"")+o;u==="moov.udta.meta.ilst"?e.loadRange([t,t+a],n):e.loadRange([t+8,t+8+8],{onSuccess:function(){i._loadAtom(e,t+8,u,n)},onError:n.onError})}else e.loadRange([t+a,t+a+8],{onSuccess:function(){i._loadAtom(e,t+a,r,n)},onError:n.onError})}_isContainerAtom(e){return["moov","udta","meta","ilst"].indexOf(e)>=0}_canReadAtom(e){return e!=="----"}_parseData(e,t){let r={};t=this._expandShortcutTags(t),this._readAtom(r,e,0,e.getSize(),t);for(let n in x)if(x.hasOwnProperty(n)){let a=r[x[n]];if(a)if(n==="track"){let o=a.data;r[n]=o.track}else r[n]=a.data}return{type:"MP4",ftyp:e.getStringAt(8,4),version:e.getLongAt(12,!0),tags:r}}_readAtom(e,t,r,n,i,a,o){o=o===void 0?"":o+" ";for(var u=r;u<r+n;){var c=t.getLongAt(u,!0);if(c==0)return;var l=t.getStringAt(u+4,4);if(this._isContainerAtom(l)){l=="meta"&&(u+=4);var d=(a?a+".":"")+l;this._readAtom(e,t,u+8,c-8,i,d,o);return}(!i||i.indexOf(l)>=0)&&a==="moov.udta.meta.ilst"&&this._canReadAtom(l)&&(e[l]=this._readMetadataAtom(t,u)),u+=c}}_readMetadataAtom(e,t){var n=e.getLongAt(t,!0),i=e.getStringAt(t+4,4),a=e.getInteger24At(t+16+1,!0);let o=ot[String(a)],u;var c=!0;if(i=="trkn")u={track:e.getShortAt(t+16+10,c),total:e.getShortAt(t+16+14,c)};else if(i=="disk")u={disk:e.getShortAt(t+16+10,c),total:e.getShortAt(t+16+14,c)};else{var l=24,d=t+l,g=n-l;switch(i==="covr"&&o==="uint8"&&(o="jpeg"),o){case"text":u=e.getStringWithCharsetAt(d,g,"utf-8").toString();break;case"uint8":u=e.getShortAt(d,!1);break;case"int":case"uint":{u=(o=="int"?g==1?e.getSByteAt:g==2?e.getSShortAt:g==4?e.getSLongAt:e.getLongAt:g==1?e.getByteAt:g==2?e.getShortAt:e.getLongAt).call(e,d+(g==8?4:0),!0);break}case"jpeg":case"png":u={format:"image/"+o,data:e.getBytesAt(d,g)};break}}return{id:i,size:n,description:st[i]||"Unknown",data:u}}getShortcuts(){return x}},ot={0:"uint8",1:"text",13:"jpeg",14:"png",21:"int",22:"uint"},st={"\xA9alb":"Album","\xA9ART":"Artist",aART:"Album Artist","\xA9day":"Release Date","\xA9nam":"Title","\xA9gen":"Genre",gnre:"Genre",trkn:"Track Number","\xA9wrt":"Composer","\xA9too":"Encoding Tool","\xA9enc":"Encoded By",cprt:"Copyright",covr:"Cover Art","\xA9grp":"Grouping",keyw:"Keywords","\xA9lyr":"Lyrics","\xA9cmt":"Comment",tmpo:"Tempo",cpil:"Compilation",disk:"Disc Number",tvsh:"TV Show Name",tven:"TV Episode ID",tvsn:"TV Season",tves:"TV Episode",tvnn:"TV Network",desc:"Description",ldes:"Long Description",sonm:"Sort Name",soar:"Sort Artist",soaa:"Sort Album",soco:"Sort Composer",sosn:"Sort Show",purd:"Purchase Date",pcst:"Podcast",purl:"Podcast URL",catg:"Category",hdvd:"HD Video",stik:"Media Type",rtng:"Content Rating",pgap:"Gapless Playback",apID:"Purchase Account",sfID:"Country Code",atID:"Artist ID",cnID:"Catalog ID",plID:"Collection ID",geID:"Genre ID","xid ":"Vendor Information",flvr:"Codec Flavor"},x={title:"\xA9nam",artist:"\xA9ART",album:"\xA9alb",year:"\xA9day",comment:"\xA9cmt",track:"trkn",genre:"\xA9gen",picture:"covr",lyrics:"\xA9lyr"};Fe.exports=J});var xe=m((Wt,Be)=>{"use strict";var ut=M(),Xt=f(),ct=4,lt=[4,132],dt=[6,134],gt=["Other","32x32 pixels 'file icon' (PNG only)","Other file icon","Cover (front)","Cover (back)","Leaflet page","Media (e.g. label side of CD)","Lead artist/lead performer/soloist","Artist/performer","Conductor","Band/Orchestra","Composer","Lyricist/text writer","Recording Location","During recording","During performance","Movie/video screen capture","A bright coloured fish","Illustration","Band/artist logotype","Publisher/Studio logotype"],Z=class extends ut{static getTagIdentifierByteRange(){return{offset:0,length:ct}}static canReadTagFormat(e){var t=String.fromCharCode.apply(String,e.slice(0,4));return t==="fLaC"}_loadData(e,t){var r=this;e.loadRange([4,7],{onSuccess:function(){r._loadBlock(e,4,t)}})}_loadBlock(e,t,r){var n=this,i=e.getByteAt(t),a=e.getInteger24At(t+1,!0);if(lt.indexOf(i)!==-1){var o=t+4;e.loadRange([o,o+a],{onSuccess:function(){n._commentOffset=o,n._nextBlock(e,t,i,a,r)}})}else if(dt.indexOf(i)!==-1){var o=t+4;e.loadRange([o,o+a],{onSuccess:function(){n._pictureOffset=o,n._nextBlock(e,t,i,a,r)}})}else n._nextBlock(e,t,i,a,r)}_nextBlock(e,t,r,n,i){var a=this;r>127?a._commentOffset?i.onSuccess():i.onError&&i.onError({type:"loadData",info:"Comment block could not be found."}):e.loadRange([t+4+n,t+4+4+n],{onSuccess:function(){a._loadBlock(e,t+4+n,i)}})}_parseData(e,t){let r=this._commentOffset;var n=e.getLongAt(r,!1),i=r+4,a=n+i,o=e.getLongAt(a,!1),u=a+4,c,l,d,g,y,h;for(let re=0;re<o;re++){let ne=e.getLongAt(u,!1),P=e.getStringWithCharsetAt(u+4,ne,"utf-8").toString(),ie=P.indexOf("="),_=[P.slice(0,ie),P.slice(ie+1)];switch(_[0].toUpperCase()){case"TITLE":c=_[1];break;case"ARTIST":l=_[1];break;case"ALBUM":d=_[1];break;case"TRACKNUMBER":g=_[1];break;case"GENRE":y=_[1];break}u+=4+ne}if(this._pictureOffset){var T=e.getLongAt(this._pictureOffset,!0),C=this._pictureOffset+4,E=e.getLongAt(C,!0),S=C+4,Ue=e.getStringAt(S,E),Q=S+E,$=e.getLongAt(Q,!0),ee=Q+4,ze=e.getStringWithCharsetAt(ee,$,"utf-8").toString(),te=ee+$+16,qe=e.getLongAt(te,!0),Ne=te+4,Xe=e.getBytesAt(Ne,qe);h={format:Ue,type:gt[T],description:ze,data:Xe}}var We={type:"FLAC",version:"1",tags:{title:c,artist:l,album:d,track:g,genre:y,picture:h}};return We}};Be.exports=Z});var Oe=m((Gt,Ie)=>{"use strict";function pt(){}Ie.exports=pt});var At=m((Vt,He)=>{var jt=f(),I=me(),yt=fe(),Tt=j(),Yt=M(),mt=Se(),ht=we(),ft=Le(),Rt=xe(),O=[],R=[];function bt(s,e){if(e===void 0)return new k(s).read();new k(s).read(e)}function Ct(s){return new k(s).read()}function Pe(s,e){let t=s.offset>=0&&s.offset+s.length>=e,r=s.offset<0&&(-s.offset>e||s.offset+s.length>0);return!(t||r)}var k=class{constructor(e){this._file=e}setTagsToRead(e){return this._tagsToRead=e,this}setFileReader(e){return this._fileReader=e,this}setTagReader(e){return this._tagReader=e,this}read(e){if(e===void 0)return new Promise((i,a)=>{this.read({onSuccess:i,onError:a})});let t=this._getFileReader(),r=new t(this._file),n=this;r.init({onSuccess:function(){n._getTagReader(r,{onSuccess:function(i){var a;new i(r).setTagsToRead((a=n._tagsToRead)!=null?a:null).read(e)},onError:e.onError})},onError:e.onError})}readAsync(){return this.read()}_getFileReader(){return this._fileReader!==void 0?this._fileReader:this._findFileReader()}_findFileReader(){for(let e=0;e<O.length;e++)if(O[e].canReadFile(this._file))return O[e];throw new Error("No suitable file reader found for "+String(this._file))}_getTagReader(e,t){if(this._tagReader!==void 0){let r=this._tagReader;setTimeout(function(){t.onSuccess(r)},1)}else this._findTagReader(e,t)}_findTagReader(e,t){let r=[],n=[],i=e.getSize();for(let u=0;u<R.length;u++){let c=R[u].getTagIdentifierByteRange();Pe(c,i)&&(c.offset>=0&&c.offset<i/2||c.offset<0&&c.offset<-i/2?r.push(R[u]):n.push(R[u]))}let a=!1,o={onSuccess:function(){if(!a){a=!0;return}for(let u=0;u<R.length;u++){let c=R[u].getTagIdentifierByteRange();if(!Pe(c,i))continue;let l;try{l=e.getBytesAt(c.offset>=0?c.offset:c.offset+i,c.length)}catch(d){let g=d instanceof Error?d.message:String(d);t.onError&&t.onError({type:"fileReader",info:g});return}if(R[u].canReadTagFormat(l)){t.onSuccess(R[u]);return}}t.onError&&t.onError({type:"tagFormat",info:"No suitable tag reader found"})},onError:t.onError};this._loadTagIdentifierRanges(e,r,o),this._loadTagIdentifierRanges(e,n,o)}_loadTagIdentifierRanges(e,t,r){if(t.length===0){setTimeout(r.onSuccess,1);return}let n=[Number.MAX_VALUE,0],i=e.getSize();for(let a=0;a<t.length;a++){let o=t[a].getTagIdentifierByteRange(),u=o.offset>=0?o.offset:o.offset+i,c=u+o.length-1;n[0]=Math.min(u,n[0]),n[1]=Math.max(c,n[1])}e.loadRange(n,r)}},F=class s{static addFileReader(e){return O.push(e),s}static addTagReader(e){return R.push(e),s}static removeTagReader(e){let t=R.indexOf(e);return t>=0&&R.splice(t,1),s}static EXPERIMENTAL_avoidHeadRequests(){I.setConfig({avoidHeadRequests:!0})}static setDisallowedXhrHeaders(e){I.setConfig({disallowedXhrHeaders:e})}static setXhrTimeoutInSec(e){I.setConfig({timeoutInSec:e})}};F.addFileReader(I).addFileReader(yt).addFileReader(Tt).addTagReader(ht).addTagReader(mt).addTagReader(ft).addTagReader(Rt);var St=Oe();St(F);He.exports={read:bt,readAsync:Ct,Reader:k,Config:F}});return At();})();
|
package/package.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@probityrules/jsmediatags",
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"description": "Media Tags Reader (ID3, MP4)",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "António Afonso",
|
|
7
|
+
"email": "antonio.afonso@gmail.com"
|
|
8
|
+
},
|
|
9
|
+
"contributors": [
|
|
10
|
+
{
|
|
11
|
+
"name": "Jacob Seidelin"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Joshua Kifer"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "Jesse Ditson",
|
|
18
|
+
"email": "jesse.ditson@gmail.com"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "Derek Detweiler",
|
|
22
|
+
"email": "derek.detweiler@gmail.com",
|
|
23
|
+
"url": "https://github.com/probityrules"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"main": "build/jsmediatags.js",
|
|
27
|
+
"types": "build/jsmediatags.d.ts",
|
|
28
|
+
"browser": "dist/jsmediatags.min.js",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./build/jsmediatags.d.ts",
|
|
32
|
+
"browser": "./dist/jsmediatags.min.js",
|
|
33
|
+
"default": "./build/jsmediatags.js"
|
|
34
|
+
},
|
|
35
|
+
"./types": {
|
|
36
|
+
"types": "./build/types.d.ts"
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"build/**/*.js",
|
|
42
|
+
"build/**/*.d.ts",
|
|
43
|
+
"dist/jsmediatags.min.js",
|
|
44
|
+
"LICENSE.md",
|
|
45
|
+
"CHANGELOG.md"
|
|
46
|
+
],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/probityrules/jsmediatags.git"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"ID3",
|
|
56
|
+
"tags",
|
|
57
|
+
"mp3",
|
|
58
|
+
"audio",
|
|
59
|
+
"mp4"
|
|
60
|
+
],
|
|
61
|
+
"license": "BSD-3-Clause",
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/probityrules/jsmediatags/issues"
|
|
64
|
+
},
|
|
65
|
+
"homepage": "https://github.com/probityrules/jsmediatags#readme",
|
|
66
|
+
"react-native": {
|
|
67
|
+
"fs": false,
|
|
68
|
+
"./NodeFileReader": false
|
|
69
|
+
},
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"xhr2": "^0.1.4"
|
|
72
|
+
},
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"buffer": "^5.0.8",
|
|
75
|
+
"react-native-fs": "^2.9.2"
|
|
76
|
+
},
|
|
77
|
+
"peerDependenciesMeta": {
|
|
78
|
+
"buffer": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"react-native-fs": {
|
|
82
|
+
"optional": true
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"devDependencies": {
|
|
86
|
+
"@types/jest": "^29.5.14",
|
|
87
|
+
"@types/node": "^20.14.0",
|
|
88
|
+
"esbuild": "^0.25.0",
|
|
89
|
+
"jest": "^29.7.0",
|
|
90
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
91
|
+
"ts-jest": "^29.4.0",
|
|
92
|
+
"typescript": "^5.6.3"
|
|
93
|
+
},
|
|
94
|
+
"scripts": {
|
|
95
|
+
"test": "jest",
|
|
96
|
+
"test:watch": "jest --watch",
|
|
97
|
+
"build": "tsc",
|
|
98
|
+
"build:browser": "node scripts/build-browser.mjs",
|
|
99
|
+
"watch": "tsc --watch",
|
|
100
|
+
"dist": "npm run build:browser",
|
|
101
|
+
"dist-watch": "node scripts/build-browser.mjs --watch",
|
|
102
|
+
"prepublishOnly": "npm run build && npm run dist"
|
|
103
|
+
},
|
|
104
|
+
"engines": {
|
|
105
|
+
"node": ">=18.0.0"
|
|
106
|
+
},
|
|
107
|
+
"overrides": {
|
|
108
|
+
"uuid": "^11.1.1"
|
|
109
|
+
}
|
|
110
|
+
}
|