@openclaw/whatsapp 2026.9.34 → 2026.9.36
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/dist/.source-module-urls/c3803b0fa58e9b1fe1f7418a46193ebc53b9c744f6359f04d40d05af48c1dce2.json +1 -0
- package/node_modules/baileys/node_modules/music-metadata/README.md +35 -32
- package/node_modules/baileys/node_modules/music-metadata/lib/ParserFactory.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ParserFactory.js +17 -13
- package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffParser.js +19 -12
- package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffToken.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffToken.js +2 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Parser.d.ts +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Parser.js +59 -16
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2TagMapper.js +1 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Token.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Token.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfGuid.js +56 -50
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfObject.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfObject.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfParser.js +15 -7
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfTagMapper.d.ts +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfTagMapper.js +21 -4
- package/node_modules/baileys/node_modules/music-metadata/lib/common/CaseInsensitiveTagMap.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/CombinedTagMapper.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/common/CombinedTagMapper.js +6 -6
- package/node_modules/baileys/node_modules/music-metadata/lib/common/FourCC.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/common/GenericTagMapper.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/GenericTagTypes.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/MetadataCollector.d.ts +3 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/MetadataCollector.js +28 -9
- package/node_modules/baileys/node_modules/music-metadata/lib/common/Util.js +25 -17
- package/node_modules/baileys/node_modules/music-metadata/lib/core.d.ts +4 -4
- package/node_modules/baileys/node_modules/music-metadata/lib/core.js +18 -11
- package/node_modules/baileys/node_modules/music-metadata/lib/dsdiff/DsdiffParser.js +29 -16
- package/node_modules/baileys/node_modules/music-metadata/lib/dsf/DsfChunk.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/dsf/DsfParser.js +3 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/EbmlIterator.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/EbmlIterator.js +35 -6
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/types.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/types.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacParser.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacParser.js +6 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacToken.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacToken.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v1/ID3v1Parser.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v1/ID3v1Parser.js +212 -42
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/AbstractID3Parser.js +5 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameHeader.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameHeader.js +8 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameParser.d.ts +2 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameParser.js +53 -22
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v22TagMapper.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v22TagMapper.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v24TagMapper.js +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2ChapterToken.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Parser.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Parser.js +32 -16
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Token.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Token.js +2 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/index.js +6 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/lrc/LyricsParser.js +3 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/matroska/MatroskaDtd.js +7 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/matroska/MatroskaParser.js +22 -11
- package/node_modules/baileys/node_modules/music-metadata/lib/matroska/types.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/Atom.d.ts +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/Atom.js +44 -11
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/AtomToken.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/AtomToken.js +30 -8
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4Parser.d.ts +2 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4Parser.js +79 -54
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4TagMapper.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/MpegLoader.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/MpegParser.js +41 -19
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/ReplayGainDataFormat.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/ReplayGainDataFormat.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/XingTag.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/MusepackParser.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/BitReader.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/MpcSv7Parser.js +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/StreamVersion7.js +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv8/MpcSv8Parser.js +7 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv8/StreamVersion8.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggParser.js +16 -12
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggToken.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/flac/FlacStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/flac/FlacStream.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/opus/OpusStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/opus/OpusStream.js +8 -4
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/speex/SpeexStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/speex/SpeexStream.js +2 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/theora/TheoraStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/Vorbis.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisDecoder.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.d.ts +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.js +14 -9
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisTagMapper.js +4 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffChunk.d.ts +3 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffChunk.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffInfoTagMap.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/type.d.ts +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/type.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveChunk.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveChunk.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveParser.d.ts +6 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveParser.js +75 -22
- package/node_modules/baileys/node_modules/music-metadata/lib/wavpack/WavPackParser.js +22 -13
- package/node_modules/baileys/node_modules/music-metadata/lib/wavpack/WavPackToken.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/package.json +3 -2
- package/package.json +4 -4
|
@@ -1,43 +1,207 @@
|
|
|
1
|
+
import { textDecode } from '@borewit/text-codec';
|
|
1
2
|
import initDebug from 'debug';
|
|
2
3
|
import { StringType, UINT8 } from 'token-types';
|
|
3
|
-
import * as util from '../common/Util.js';
|
|
4
|
-
import { BasicParser } from '../common/BasicParser.js';
|
|
5
4
|
import { APEv2Parser } from '../apev2/APEv2Parser.js';
|
|
6
|
-
import {
|
|
5
|
+
import { BasicParser } from '../common/BasicParser.js';
|
|
6
|
+
import * as util from '../common/Util.js';
|
|
7
7
|
const debug = initDebug('music-metadata:parser:ID3v1');
|
|
8
8
|
/**
|
|
9
9
|
* ID3v1 Genre mappings
|
|
10
10
|
* Ref: https://de.wikipedia.org/wiki/Liste_der_ID3v1-Genres
|
|
11
11
|
*/
|
|
12
12
|
export const Genres = [
|
|
13
|
-
'Blues',
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
13
|
+
'Blues',
|
|
14
|
+
'Classic Rock',
|
|
15
|
+
'Country',
|
|
16
|
+
'Dance',
|
|
17
|
+
'Disco',
|
|
18
|
+
'Funk',
|
|
19
|
+
'Grunge',
|
|
20
|
+
'Hip-Hop',
|
|
21
|
+
'Jazz',
|
|
22
|
+
'Metal',
|
|
23
|
+
'New Age',
|
|
24
|
+
'Oldies',
|
|
25
|
+
'Other',
|
|
26
|
+
'Pop',
|
|
27
|
+
'R&B',
|
|
28
|
+
'Rap',
|
|
29
|
+
'Reggae',
|
|
30
|
+
'Rock',
|
|
31
|
+
'Techno',
|
|
32
|
+
'Industrial',
|
|
33
|
+
'Alternative',
|
|
34
|
+
'Ska',
|
|
35
|
+
'Death Metal',
|
|
36
|
+
'Pranks',
|
|
37
|
+
'Soundtrack',
|
|
38
|
+
'Euro-Techno',
|
|
39
|
+
'Ambient',
|
|
40
|
+
'Trip-Hop',
|
|
41
|
+
'Vocal',
|
|
42
|
+
'Jazz+Funk',
|
|
43
|
+
'Fusion',
|
|
44
|
+
'Trance',
|
|
45
|
+
'Classical',
|
|
46
|
+
'Instrumental',
|
|
47
|
+
'Acid',
|
|
48
|
+
'House',
|
|
49
|
+
'Game',
|
|
50
|
+
'Sound Clip',
|
|
51
|
+
'Gospel',
|
|
52
|
+
'Noise',
|
|
53
|
+
'Alt. Rock',
|
|
54
|
+
'Bass',
|
|
55
|
+
'Soul',
|
|
56
|
+
'Punk',
|
|
57
|
+
'Space',
|
|
58
|
+
'Meditative',
|
|
59
|
+
'Instrumental Pop',
|
|
60
|
+
'Instrumental Rock',
|
|
61
|
+
'Ethnic',
|
|
62
|
+
'Gothic',
|
|
63
|
+
'Darkwave',
|
|
64
|
+
'Techno-Industrial',
|
|
65
|
+
'Electronic',
|
|
66
|
+
'Pop-Folk',
|
|
67
|
+
'Eurodance',
|
|
68
|
+
'Dream',
|
|
69
|
+
'Southern Rock',
|
|
70
|
+
'Comedy',
|
|
71
|
+
'Cult',
|
|
72
|
+
'Gangsta Rap',
|
|
73
|
+
'Top 40',
|
|
74
|
+
'Christian Rap',
|
|
75
|
+
'Pop/Funk',
|
|
76
|
+
'Jungle',
|
|
77
|
+
'Native American',
|
|
78
|
+
'Cabaret',
|
|
79
|
+
'New Wave',
|
|
80
|
+
'Psychedelic',
|
|
81
|
+
'Rave',
|
|
82
|
+
'Showtunes',
|
|
83
|
+
'Trailer',
|
|
84
|
+
'Lo-Fi',
|
|
85
|
+
'Tribal',
|
|
86
|
+
'Acid Punk',
|
|
87
|
+
'Acid Jazz',
|
|
88
|
+
'Polka',
|
|
89
|
+
'Retro',
|
|
90
|
+
'Musical',
|
|
91
|
+
'Rock & Roll',
|
|
92
|
+
'Hard Rock',
|
|
93
|
+
'Folk',
|
|
94
|
+
'Folk/Rock',
|
|
95
|
+
'National Folk',
|
|
96
|
+
'Swing',
|
|
97
|
+
'Fast-Fusion',
|
|
98
|
+
'Bebob',
|
|
99
|
+
'Latin',
|
|
100
|
+
'Revival',
|
|
101
|
+
'Celtic',
|
|
102
|
+
'Bluegrass',
|
|
103
|
+
'Avantgarde',
|
|
104
|
+
'Gothic Rock',
|
|
105
|
+
'Progressive Rock',
|
|
106
|
+
'Psychedelic Rock',
|
|
107
|
+
'Symphonic Rock',
|
|
108
|
+
'Slow Rock',
|
|
109
|
+
'Big Band',
|
|
110
|
+
'Chorus',
|
|
111
|
+
'Easy Listening',
|
|
112
|
+
'Acoustic',
|
|
113
|
+
'Humour',
|
|
114
|
+
'Speech',
|
|
115
|
+
'Chanson',
|
|
116
|
+
'Opera',
|
|
117
|
+
'Chamber Music',
|
|
118
|
+
'Sonata',
|
|
119
|
+
'Symphony',
|
|
120
|
+
'Booty Bass',
|
|
121
|
+
'Primus',
|
|
122
|
+
'Porn Groove',
|
|
123
|
+
'Satire',
|
|
124
|
+
'Slow Jam',
|
|
125
|
+
'Club',
|
|
126
|
+
'Tango',
|
|
127
|
+
'Samba',
|
|
128
|
+
'Folklore',
|
|
129
|
+
'Ballad',
|
|
130
|
+
'Power Ballad',
|
|
131
|
+
'Rhythmic Soul',
|
|
132
|
+
'Freestyle',
|
|
133
|
+
'Duet',
|
|
134
|
+
'Punk Rock',
|
|
135
|
+
'Drum Solo',
|
|
136
|
+
'A Cappella',
|
|
137
|
+
'Euro-House',
|
|
138
|
+
'Dance Hall',
|
|
139
|
+
'Goa',
|
|
140
|
+
'Drum & Bass',
|
|
141
|
+
'Club-House',
|
|
142
|
+
'Hardcore',
|
|
143
|
+
'Terror',
|
|
144
|
+
'Indie',
|
|
145
|
+
'BritPop',
|
|
146
|
+
'Negerpunk',
|
|
147
|
+
'Polsk Punk',
|
|
148
|
+
'Beat',
|
|
149
|
+
'Christian Gangsta Rap',
|
|
150
|
+
'Heavy Metal',
|
|
151
|
+
'Black Metal',
|
|
152
|
+
'Crossover',
|
|
153
|
+
'Contemporary Christian',
|
|
154
|
+
'Christian Rock',
|
|
155
|
+
'Merengue',
|
|
156
|
+
'Salsa',
|
|
157
|
+
'Thrash Metal',
|
|
158
|
+
'Anime',
|
|
159
|
+
'JPop',
|
|
160
|
+
'Synthpop',
|
|
161
|
+
'Abstract',
|
|
162
|
+
'Art Rock',
|
|
163
|
+
'Baroque',
|
|
164
|
+
'Bhangra',
|
|
165
|
+
'Big Beat',
|
|
166
|
+
'Breakbeat',
|
|
167
|
+
'Chillout',
|
|
168
|
+
'Downtempo',
|
|
169
|
+
'Dub',
|
|
170
|
+
'EBM',
|
|
171
|
+
'Eclectic',
|
|
172
|
+
'Electro',
|
|
173
|
+
'Electroclash',
|
|
174
|
+
'Emo',
|
|
175
|
+
'Experimental',
|
|
176
|
+
'Garage',
|
|
177
|
+
'Global',
|
|
178
|
+
'IDM',
|
|
179
|
+
'Illbient',
|
|
180
|
+
'Industro-Goth',
|
|
181
|
+
'Jam Band',
|
|
182
|
+
'Krautrock',
|
|
183
|
+
'Leftfield',
|
|
184
|
+
'Lounge',
|
|
185
|
+
'Math Rock',
|
|
186
|
+
'New Romantic',
|
|
187
|
+
'Nu-Breakz',
|
|
188
|
+
'Post-Punk',
|
|
189
|
+
'Post-Rock',
|
|
190
|
+
'Psytrance',
|
|
191
|
+
'Shoegaze',
|
|
192
|
+
'Space Rock',
|
|
193
|
+
'Trop Rock',
|
|
194
|
+
'World Music',
|
|
195
|
+
'Neoclassical',
|
|
196
|
+
'Audiobook',
|
|
197
|
+
'Audio Theatre',
|
|
198
|
+
'Neue Deutsche Welle',
|
|
199
|
+
'Podcast',
|
|
200
|
+
'Indie Rock',
|
|
201
|
+
'G-Funk',
|
|
202
|
+
'Dubstep',
|
|
203
|
+
'Garage Rock',
|
|
204
|
+
'Psybient'
|
|
41
205
|
];
|
|
42
206
|
/**
|
|
43
207
|
* Spec: http://id3.org/ID3v1
|
|
@@ -46,25 +210,29 @@ export const Genres = [
|
|
|
46
210
|
const Iid3v1Token = {
|
|
47
211
|
len: 128,
|
|
48
212
|
/**
|
|
49
|
-
* @param buf Buffer possibly holding the 128
|
|
213
|
+
* @param buf Buffer possibly holding the 128-byte ID3v1/1.1 metadata header
|
|
50
214
|
* @param off Offset in buffer in bytes
|
|
51
|
-
* @returns ID3v1.1 header if first 3 bytes
|
|
215
|
+
* @returns ID3v1/1.1 header if the first 3 bytes equal 'TAG', otherwise null is returned
|
|
52
216
|
*/
|
|
53
217
|
get: (buf, off) => {
|
|
54
218
|
const header = new Id3v1StringType(3).get(buf, off);
|
|
55
|
-
|
|
219
|
+
if (header !== 'TAG') {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const zeroByte = UINT8.get(buf, off + 125);
|
|
223
|
+
const track = UINT8.get(buf, off + 126);
|
|
224
|
+
// ID3v1.1 replaces the final two comment bytes with a zero separator and a nonzero track number.
|
|
225
|
+
const hasTrack = zeroByte === 0 && track !== 0;
|
|
226
|
+
return {
|
|
56
227
|
header,
|
|
57
228
|
title: new Id3v1StringType(30).get(buf, off + 3),
|
|
58
229
|
artist: new Id3v1StringType(30).get(buf, off + 33),
|
|
59
230
|
album: new Id3v1StringType(30).get(buf, off + 63),
|
|
60
231
|
year: new Id3v1StringType(4).get(buf, off + 93),
|
|
61
|
-
comment: new Id3v1StringType(28).get(buf, off + 97),
|
|
62
|
-
|
|
63
|
-
zeroByte: UINT8.get(buf, off + 127),
|
|
64
|
-
// track: ID3v1.1 field added by Michael Mutschler
|
|
65
|
-
track: UINT8.get(buf, off + 126),
|
|
232
|
+
comment: new Id3v1StringType(hasTrack ? 28 : 30).get(buf, off + 97),
|
|
233
|
+
track: hasTrack ? track : undefined,
|
|
66
234
|
genre: UINT8.get(buf, off + 127)
|
|
67
|
-
}
|
|
235
|
+
};
|
|
68
236
|
}
|
|
69
237
|
};
|
|
70
238
|
class Id3v1StringType {
|
|
@@ -110,12 +278,14 @@ export class ID3v1Parser extends BasicParser {
|
|
|
110
278
|
debug('ID3v1 header found at: pos=%s', this.tokenizer.fileInfo.size - Iid3v1Token.len);
|
|
111
279
|
const props = ['title', 'artist', 'album', 'comment', 'track', 'year'];
|
|
112
280
|
for (const id of props) {
|
|
113
|
-
if (header[id] && header[id] !== '')
|
|
281
|
+
if (header[id] && header[id] !== '') {
|
|
114
282
|
await this.addTag(id, header[id]);
|
|
283
|
+
}
|
|
115
284
|
}
|
|
116
285
|
const genre = ID3v1Parser.getGenre(header.genre);
|
|
117
|
-
if (genre)
|
|
286
|
+
if (genre) {
|
|
118
287
|
await this.addTag('genre', genre);
|
|
288
|
+
}
|
|
119
289
|
}
|
|
120
290
|
else {
|
|
121
291
|
debug('ID3v1 header not found at: pos=%s', this.tokenizer.fileInfo.size - Iid3v1Token.len);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { EndOfStreamError } from 'strtok3';
|
|
2
1
|
import initDebug from 'debug';
|
|
3
|
-
import {
|
|
4
|
-
import { ID3v2Parser } from './ID3v2Parser.js';
|
|
5
|
-
import { ID3v1Parser } from '../id3v1/ID3v1Parser.js';
|
|
2
|
+
import { EndOfStreamError } from 'strtok3';
|
|
6
3
|
import { BasicParser } from '../common/BasicParser.js';
|
|
4
|
+
import { ID3v1Parser } from '../id3v1/ID3v1Parser.js';
|
|
5
|
+
import { ID3v2Parser } from './ID3v2Parser.js';
|
|
6
|
+
import { ID3v2Header } from './ID3v2Token.js';
|
|
7
7
|
const debug = initDebug('music-metadata:parser:ID3');
|
|
8
8
|
/**
|
|
9
9
|
* Abstract parser which tries take ID3v2 and ID3v1 headers.
|
|
@@ -22,7 +22,7 @@ export class AbstractID3Parser extends BasicParser {
|
|
|
22
22
|
}
|
|
23
23
|
catch (err) {
|
|
24
24
|
if (err instanceof EndOfStreamError) {
|
|
25
|
-
debug(
|
|
25
|
+
debug('End-of-stream');
|
|
26
26
|
}
|
|
27
27
|
else {
|
|
28
28
|
throw err;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type ID3v2MajorVersion } from './ID3v2Token.js';
|
|
2
1
|
import type { IWarningCollector } from '../common/MetadataCollector.js';
|
|
2
|
+
import { type ID3v2MajorVersion } from './ID3v2Token.js';
|
|
3
3
|
export interface IFrameFlags {
|
|
4
4
|
status: {
|
|
5
5
|
tag_alter_preservation: boolean;
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
// lib/id3v2/FrameHeader.ts
|
|
2
|
+
import { textDecode } from '@borewit/text-codec';
|
|
2
3
|
import * as Token from 'token-types';
|
|
3
4
|
import * as util from '../common/Util.js';
|
|
4
|
-
import { UINT32SYNCSAFE } from './ID3v2Token.js';
|
|
5
|
-
import { textDecode } from '@borewit/text-codec';
|
|
6
5
|
import { Id3v2ContentError } from './FrameParser.js';
|
|
6
|
+
import { UINT32SYNCSAFE } from './ID3v2Token.js';
|
|
7
7
|
/**
|
|
8
8
|
* Frame header length (bytes) depending on ID3v2 major version.
|
|
9
9
|
*/
|
|
10
10
|
export function getFrameHeaderLength(majorVer) {
|
|
11
11
|
switch (majorVer) {
|
|
12
|
-
case 2:
|
|
12
|
+
case 2:
|
|
13
|
+
return 6;
|
|
13
14
|
case 3:
|
|
14
|
-
case 4:
|
|
15
|
-
|
|
15
|
+
case 4:
|
|
16
|
+
return 10;
|
|
17
|
+
default:
|
|
18
|
+
throw makeUnexpectedMajorVersionError(majorVer);
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
function readFrameFlags(b, majorVer) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type ID3v2MajorVersion, type ITextEncoding } from './ID3v2Token.js';
|
|
2
1
|
import type { IWarningCollector } from '../common/MetadataCollector.js';
|
|
3
2
|
import { type IChapterInfo } from './ID3v2ChapterToken.js';
|
|
3
|
+
import { type ID3v2MajorVersion, type ITextEncoding } from './ID3v2Token.js';
|
|
4
4
|
interface ICustomTag {
|
|
5
5
|
owner_identifier: string;
|
|
6
6
|
}
|
|
@@ -65,6 +65,7 @@ export declare class FrameParser {
|
|
|
65
65
|
/**
|
|
66
66
|
* id3v2.4 defines that multiple T* values are separated by 0x00
|
|
67
67
|
* id3v2.3 defines that TCOM, TEXT, TOLY, TOPE & TPE1 values are separated by /
|
|
68
|
+
* (TCON/TCO genre values are NOT slash-separated in ID3v2.3)
|
|
68
69
|
* @param tag - Tag name
|
|
69
70
|
* @param text - Concatenated tag value
|
|
70
71
|
* @returns Split tag value
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import initDebug from 'debug';
|
|
2
2
|
import * as Token from 'token-types';
|
|
3
3
|
import * as util from '../common/Util.js';
|
|
4
|
-
import {
|
|
4
|
+
import { decodeUintBE } from '../common/Util.js';
|
|
5
5
|
import { Genres } from '../id3v1/ID3v1Parser.js';
|
|
6
6
|
import { makeUnexpectedFileContentError } from '../ParseError.js';
|
|
7
|
-
import { decodeUintBE } from '../common/Util.js';
|
|
8
|
-
import { ChapterInfo } from './ID3v2ChapterToken.js';
|
|
9
7
|
import { getFrameHeaderLength, readFrameHeader } from './FrameHeader.js';
|
|
8
|
+
import { ChapterInfo } from './ID3v2ChapterToken.js';
|
|
9
|
+
import { AttachedPictureType, SyncTextHeader, TextEncodingToken, TextHeader } from './ID3v2Token.js';
|
|
10
10
|
const debug = initDebug('music-metadata:id3v2:frame-parser');
|
|
11
11
|
const defaultEnc = 'latin1'; // latin1 == iso-8859-1;
|
|
12
12
|
const urlEnc = { encoding: defaultEnc, bom: false };
|
|
@@ -32,8 +32,9 @@ export function parseGenre(origVal) {
|
|
|
32
32
|
}
|
|
33
33
|
code = undefined;
|
|
34
34
|
}
|
|
35
|
-
else
|
|
35
|
+
else {
|
|
36
36
|
code += c;
|
|
37
|
+
}
|
|
37
38
|
}
|
|
38
39
|
else if (c === '(') {
|
|
39
40
|
code = '';
|
|
@@ -53,10 +54,12 @@ export function parseGenre(origVal) {
|
|
|
53
54
|
return genres;
|
|
54
55
|
}
|
|
55
56
|
function parseGenreCode(code) {
|
|
56
|
-
if (code === 'RX')
|
|
57
|
+
if (code === 'RX') {
|
|
57
58
|
return 'Remix';
|
|
58
|
-
|
|
59
|
+
}
|
|
60
|
+
if (code === 'CR') {
|
|
59
61
|
return 'Cover';
|
|
62
|
+
}
|
|
60
63
|
if (code.match(/^\d*$/)) {
|
|
61
64
|
return Genres[Number.parseInt(code, 10)];
|
|
62
65
|
}
|
|
@@ -128,13 +131,15 @@ export class FrameParser {
|
|
|
128
131
|
break;
|
|
129
132
|
case 'TCO':
|
|
130
133
|
case 'TCON':
|
|
131
|
-
output = this.splitValue(type, text)
|
|
134
|
+
output = this.splitValue(type, text)
|
|
135
|
+
.map(v => parseGenre(v))
|
|
136
|
+
.reduce((acc, val) => acc.concat(val), []);
|
|
132
137
|
break;
|
|
133
138
|
case 'PCS':
|
|
134
139
|
case 'PCST':
|
|
135
140
|
// TODO: Why `default` not results `1` but `''`?
|
|
136
141
|
output = this.major >= 4 ? this.splitValue(type, text) : [text];
|
|
137
|
-
output =
|
|
142
|
+
output = Array.isArray(output) && output[0] === '' ? 1 : 0;
|
|
138
143
|
break;
|
|
139
144
|
default:
|
|
140
145
|
output = this.major >= 4 ? this.splitValue(type, text) : [text];
|
|
@@ -234,12 +239,14 @@ export class FrameParser {
|
|
|
234
239
|
output = { owner_identifier: ufid.id, identifier: ufid.data };
|
|
235
240
|
break;
|
|
236
241
|
}
|
|
237
|
-
case 'PRIV': {
|
|
242
|
+
case 'PRIV': {
|
|
243
|
+
// private frame
|
|
238
244
|
const priv = FrameParser.readIdentifierAndData(uint8Array, defaultEnc);
|
|
239
245
|
output = { owner_identifier: priv.id, data: priv.data };
|
|
240
246
|
break;
|
|
241
247
|
}
|
|
242
|
-
case 'POPM': {
|
|
248
|
+
case 'POPM': {
|
|
249
|
+
// Popularimeter
|
|
243
250
|
uint8Array = uint8Array.subarray(offset);
|
|
244
251
|
const emailStr = FrameParser.readNullTerminatedString(uint8Array, urlEnc);
|
|
245
252
|
const email = emailStr.text;
|
|
@@ -258,7 +265,8 @@ export class FrameParser {
|
|
|
258
265
|
};
|
|
259
266
|
break;
|
|
260
267
|
}
|
|
261
|
-
case 'GEOB': {
|
|
268
|
+
case 'GEOB': {
|
|
269
|
+
// General encapsulated object
|
|
262
270
|
// [encoding] <MIME> 0x00 <filename> 0x00/0x00 0x00 <description> 0x00/0x00 0x00 <data>
|
|
263
271
|
const encoding = TextEncodingToken.get(uint8Array, 0);
|
|
264
272
|
uint8Array = uint8Array.subarray(1);
|
|
@@ -317,8 +325,9 @@ export class FrameParser {
|
|
|
317
325
|
}
|
|
318
326
|
// ID3v2 Chapters 1.0
|
|
319
327
|
// https://mutagen-specs.readthedocs.io/en/latest/id3/id3v2-chapters-1.0.html#chapter-frame
|
|
320
|
-
case 'CHAP': {
|
|
321
|
-
|
|
328
|
+
case 'CHAP': {
|
|
329
|
+
// // Chapter frame
|
|
330
|
+
debug('Reading CHAP');
|
|
322
331
|
fzero = util.findZero(uint8Array, defaultEnc);
|
|
323
332
|
const chapter = {
|
|
324
333
|
label: util.decodeString(uint8Array.subarray(0, fzero), defaultEnc),
|
|
@@ -339,7 +348,8 @@ export class FrameParser {
|
|
|
339
348
|
}
|
|
340
349
|
// ID3v2 Chapters 1.0
|
|
341
350
|
// https://mutagen-specs.readthedocs.io/en/latest/id3/id3v2-chapters-1.0.html#table-of-contents-frame
|
|
342
|
-
case 'CTOC': {
|
|
351
|
+
case 'CTOC': {
|
|
352
|
+
// Table of contents frame
|
|
343
353
|
debug('Reading CTOC');
|
|
344
354
|
// Element ID (null-terminated latin1)
|
|
345
355
|
const idEnd = util.findZero(uint8Array, defaultEnc);
|
|
@@ -383,21 +393,19 @@ export class FrameParser {
|
|
|
383
393
|
return output;
|
|
384
394
|
}
|
|
385
395
|
static readNullTerminatedString(uint8Array, encoding) {
|
|
386
|
-
const bomSize = encoding.bom ? 2 : 0;
|
|
387
396
|
const originalLen = uint8Array.length;
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
// No terminator found, decode full buffer remainder
|
|
397
|
+
const zeroIndex = util.findZero(uint8Array, encoding.encoding);
|
|
398
|
+
if (zeroIndex >= originalLen) {
|
|
399
|
+
// No terminator found, decode the whole buffer
|
|
392
400
|
return {
|
|
393
401
|
text: util.decodeString(uint8Array, encoding.encoding),
|
|
394
402
|
len: originalLen
|
|
395
403
|
};
|
|
396
404
|
}
|
|
397
|
-
const txt = uint8Array.subarray(0,
|
|
405
|
+
const txt = uint8Array.subarray(0, zeroIndex);
|
|
398
406
|
return {
|
|
399
407
|
text: util.decodeString(txt, encoding.encoding),
|
|
400
|
-
len:
|
|
408
|
+
len: zeroIndex + FrameParser.getNullTerminatorLength(encoding.encoding)
|
|
401
409
|
};
|
|
402
410
|
}
|
|
403
411
|
static fixPictureMimeType(pictureType) {
|
|
@@ -425,6 +433,7 @@ export class FrameParser {
|
|
|
425
433
|
/**
|
|
426
434
|
* id3v2.4 defines that multiple T* values are separated by 0x00
|
|
427
435
|
* id3v2.3 defines that TCOM, TEXT, TOLY, TOPE & TPE1 values are separated by /
|
|
436
|
+
* (TCON/TCO genre values are NOT slash-separated in ID3v2.3)
|
|
428
437
|
* @param tag - Tag name
|
|
429
438
|
* @param text - Concatenated tag value
|
|
430
439
|
* @returns Split tag value
|
|
@@ -436,7 +445,29 @@ export class FrameParser {
|
|
|
436
445
|
if (values.length > 1) {
|
|
437
446
|
this.warningCollector.addWarning(`ID3v2.${this.major} ${tag} uses non standard null-separator.`);
|
|
438
447
|
}
|
|
439
|
-
else
|
|
448
|
+
else if ([
|
|
449
|
+
/* v2.3: */ 'TPE1',
|
|
450
|
+
'TPE2',
|
|
451
|
+
'TPE3',
|
|
452
|
+
'TPE4',
|
|
453
|
+
'TCOM',
|
|
454
|
+
'TEXT',
|
|
455
|
+
'TOLY',
|
|
456
|
+
'TOPE',
|
|
457
|
+
/* v2.2: */ 'TP1',
|
|
458
|
+
'TCM',
|
|
459
|
+
'TXT',
|
|
460
|
+
'TOA',
|
|
461
|
+
'TOL',
|
|
462
|
+
// Picard can flatten multiple values with '/' in these frames.
|
|
463
|
+
// https://picard-docs.musicbrainz.org/en/v2.13/config/options_tags_compatibility_id3.html
|
|
464
|
+
'TXXX',
|
|
465
|
+
'TSRC',
|
|
466
|
+
// Retain legacy support for nonstandard slash-separated credits.
|
|
467
|
+
'IPLS'
|
|
468
|
+
].includes(tag)) {
|
|
469
|
+
// note that field Genre (TCON/TCO) is NOT in this list:
|
|
470
|
+
// a genre like "Duo Cello/Piano" must stay intact
|
|
440
471
|
values = text.split(/\//g);
|
|
441
472
|
}
|
|
442
473
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UINT32_LE } from 'token-types';
|
|
2
|
-
import { CommonTagMapper } from '../common/GenericTagMapper.js';
|
|
3
2
|
import { CaseInsensitiveTagMap } from '../common/CaseInsensitiveTagMap.js';
|
|
3
|
+
import { CommonTagMapper } from '../common/GenericTagMapper.js';
|
|
4
4
|
import { decodeString } from '../common/Util.js';
|
|
5
5
|
/**
|
|
6
6
|
* ID3v2.3/ID3v2.4 tag mappings
|
|
@@ -138,13 +138,13 @@ const id3v24TagMap = {
|
|
|
138
138
|
TKWD: 'keywords',
|
|
139
139
|
WFED: 'podcasturl',
|
|
140
140
|
GRP1: 'grouping',
|
|
141
|
-
PCNT: 'playCounter'
|
|
141
|
+
PCNT: 'playCounter'
|
|
142
142
|
};
|
|
143
143
|
export class ID3v24TagMapper extends CaseInsensitiveTagMap {
|
|
144
144
|
static toRating(popm) {
|
|
145
145
|
return {
|
|
146
146
|
source: popm.email,
|
|
147
|
-
rating: popm.rating > 0 ? (popm.rating - 1) / 254 * CommonTagMapper.maxRatingScore : undefined
|
|
147
|
+
rating: popm.rating > 0 ? ((popm.rating - 1) / 254) * CommonTagMapper.maxRatingScore : undefined
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
150
|
constructor() {
|
|
@@ -10,8 +10,8 @@ export const ChapterInfo = {
|
|
|
10
10
|
return {
|
|
11
11
|
startTime: Token.UINT32_BE.get(buf, off),
|
|
12
12
|
endTime: Token.UINT32_BE.get(buf, off + 4),
|
|
13
|
-
startOffset: startOffset ===
|
|
14
|
-
endOffset: endOffset ===
|
|
13
|
+
startOffset: startOffset === 0xffffffff ? undefined : startOffset,
|
|
14
|
+
endOffset: endOffset === 0xffffffff ? undefined : endOffset
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ITokenizer } from 'strtok3';
|
|
2
|
-
import type { IOptions } from '../type.js';
|
|
3
2
|
import type { INativeMetadataCollector } from '../common/MetadataCollector.js';
|
|
3
|
+
import type { IOptions } from '../type.js';
|
|
4
4
|
export declare class ID3v2Parser {
|
|
5
5
|
static removeUnsyncBytes(buffer: Uint8Array): Uint8Array;
|
|
6
6
|
private static readFrameData;
|