taglib-wasm 2.1.0 → 2.2.1
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/index.browser.js +54 -12
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/simple.browser.js +113 -13
- package/dist/src/constants/properties.d.ts +14 -0
- package/dist/src/constants/properties.d.ts.map +1 -1
- package/dist/src/constants/specialized-properties.d.ts +14 -0
- package/dist/src/constants/specialized-properties.d.ts.map +1 -1
- package/dist/src/constants/specialized-properties.js +22 -0
- package/dist/src/folder-api/folder-operations.d.ts +2 -30
- package/dist/src/folder-api/folder-operations.d.ts.map +1 -1
- package/dist/src/folder-api/folder-operations.js +1 -36
- package/dist/src/folder-api/index.d.ts +2 -2
- package/dist/src/folder-api/index.d.ts.map +1 -1
- package/dist/src/folder-api/index.js +2 -7
- package/dist/src/folder-api/types.d.ts +0 -21
- package/dist/src/folder-api/types.d.ts.map +1 -1
- package/dist/src/folder-api/types.js +1 -13
- package/dist/src/simple/batch-operations.d.ts +74 -2
- package/dist/src/simple/batch-operations.d.ts.map +1 -1
- package/dist/src/simple/batch-operations.js +66 -6
- package/dist/src/simple/index.d.ts +2 -2
- package/dist/src/simple/index.d.ts.map +1 -1
- package/dist/src/simple/index.js +6 -2
- package/dist/src/simple/tag-operations.d.ts +5 -1
- package/dist/src/simple/tag-operations.d.ts.map +1 -1
- package/dist/src/simple/tag-operations.js +5 -2
- package/dist/src/types/metadata-mappings.d.ts +1 -1
- package/dist/src/types/metadata-mappings.d.ts.map +1 -1
- package/dist/src/types/metadata-mappings.js +5 -0
- package/dist/src/types/tags.d.ts +13 -0
- package/dist/src/types/tags.d.ts.map +1 -1
- package/dist/src/utils/tag-mapping.d.ts +9 -1
- package/dist/src/utils/tag-mapping.d.ts.map +1 -1
- package/dist/src/utils/tag-mapping.js +22 -5
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/taglib-wasi.wasm +0 -0
- package/dist/taglib-web.wasm +0 -0
- package/package.json +1 -1
package/dist/index.browser.js
CHANGED
|
@@ -1387,6 +1387,28 @@ var init_specialized_properties = __esm({
|
|
|
1387
1387
|
mp4: "----:com.apple.iTunes:MusicBrainz Album Type"
|
|
1388
1388
|
}
|
|
1389
1389
|
},
|
|
1390
|
+
releaseCountry: {
|
|
1391
|
+
key: "RELEASECOUNTRY",
|
|
1392
|
+
description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY",
|
|
1393
|
+
type: "string",
|
|
1394
|
+
supportedFormats: [
|
|
1395
|
+
"ID3v2",
|
|
1396
|
+
"MP4",
|
|
1397
|
+
"Vorbis",
|
|
1398
|
+
"APE",
|
|
1399
|
+
"ASF",
|
|
1400
|
+
"Matroska",
|
|
1401
|
+
"WAV"
|
|
1402
|
+
],
|
|
1403
|
+
mappings: {
|
|
1404
|
+
id3v2: {
|
|
1405
|
+
frame: "TXXX",
|
|
1406
|
+
description: "MusicBrainz Album Release Country"
|
|
1407
|
+
},
|
|
1408
|
+
vorbis: "RELEASECOUNTRY",
|
|
1409
|
+
mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country"
|
|
1410
|
+
}
|
|
1411
|
+
},
|
|
1390
1412
|
itunesAdvisory: {
|
|
1391
1413
|
key: "ITUNESADVISORY",
|
|
1392
1414
|
description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here",
|
|
@@ -2765,8 +2787,9 @@ var init_mirror_fields = __esm({
|
|
|
2765
2787
|
});
|
|
2766
2788
|
|
|
2767
2789
|
// src/utils/tag-mapping.ts
|
|
2768
|
-
function readExtendedTag(audioFile) {
|
|
2769
|
-
const
|
|
2790
|
+
function readExtendedTag(audioFile, includeProperties) {
|
|
2791
|
+
const props = audioFile.properties();
|
|
2792
|
+
const tag = mapPropertiesToExtendedTag(props);
|
|
2770
2793
|
const pictures = audioFile.getPictures();
|
|
2771
2794
|
if (pictures.length > 0) tag.pictures = pictures;
|
|
2772
2795
|
const ratings = audioFile.getRatings();
|
|
@@ -2781,6 +2804,18 @@ function readExtendedTag(audioFile) {
|
|
|
2781
2804
|
if (bextData !== void 0) tag.bextData = bextData;
|
|
2782
2805
|
const ixml = audioFile.getIxml();
|
|
2783
2806
|
if (ixml !== void 0) tag.ixml = ixml;
|
|
2807
|
+
if (includeProperties !== void 0 && includeProperties.length > 0) {
|
|
2808
|
+
const extraProperties = {};
|
|
2809
|
+
for (const wireKey of includeProperties) {
|
|
2810
|
+
const values = props[fromTagLibKey(wireKey)]?.filter((v) => v !== "");
|
|
2811
|
+
if (values !== void 0 && values.length > 0) {
|
|
2812
|
+
extraProperties[wireKey] = values;
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
if (Object.keys(extraProperties).length > 0) {
|
|
2816
|
+
tag.extraProperties = extraProperties;
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2784
2819
|
return tag;
|
|
2785
2820
|
}
|
|
2786
2821
|
function mapPropertiesToExtendedTag(props) {
|
|
@@ -2844,14 +2879,16 @@ function mapPropertiesToExtendedTag(props) {
|
|
|
2844
2879
|
}
|
|
2845
2880
|
return tag;
|
|
2846
2881
|
}
|
|
2847
|
-
function
|
|
2848
|
-
const currentProps = file.properties();
|
|
2882
|
+
function mergeTagUpdatesInto(currentProps, tags) {
|
|
2849
2883
|
const newProps = normalizeTagInput(tags);
|
|
2850
2884
|
reconcilePairFields(currentProps, newProps, tags);
|
|
2851
2885
|
if (newProps.date !== void 0 || newProps.year !== void 0) {
|
|
2852
2886
|
currentProps.YEAR = [];
|
|
2853
2887
|
}
|
|
2854
|
-
|
|
2888
|
+
return { ...currentProps, ...newProps };
|
|
2889
|
+
}
|
|
2890
|
+
function mergeTagUpdates(file, tags) {
|
|
2891
|
+
file.setProperties(mergeTagUpdatesInto(file.properties(), tags));
|
|
2855
2892
|
}
|
|
2856
2893
|
function reconcilePairFields(currentProps, newProps, input) {
|
|
2857
2894
|
const pairs = [
|
|
@@ -2900,6 +2937,7 @@ function normalizeTagInput(input) {
|
|
|
2900
2937
|
}
|
|
2901
2938
|
for (const [field, val] of Object.entries(input)) {
|
|
2902
2939
|
if (BASIC_FIELDS.has(field) || val === void 0) continue;
|
|
2940
|
+
if (field === "extraProperties") continue;
|
|
2903
2941
|
if (field === "compilation") {
|
|
2904
2942
|
props[field] = [val ? "1" : "0"];
|
|
2905
2943
|
} else if (field === "advisory") {
|
|
@@ -2966,7 +3004,7 @@ var VERSION;
|
|
|
2966
3004
|
var init_version = __esm({
|
|
2967
3005
|
"src/version.ts"() {
|
|
2968
3006
|
"use strict";
|
|
2969
|
-
VERSION = "2.1
|
|
3007
|
+
VERSION = "2.2.1";
|
|
2970
3008
|
}
|
|
2971
3009
|
});
|
|
2972
3010
|
|
|
@@ -3321,8 +3359,11 @@ async function withAudioFileSaveToFile(file, fn) {
|
|
|
3321
3359
|
}
|
|
3322
3360
|
|
|
3323
3361
|
// src/simple/tag-operations.ts
|
|
3324
|
-
async function readTags(file) {
|
|
3325
|
-
return withAudioFile(
|
|
3362
|
+
async function readTags(file, options = {}) {
|
|
3363
|
+
return withAudioFile(
|
|
3364
|
+
file,
|
|
3365
|
+
(audioFile) => readExtendedTag(audioFile, options.includeProperties)
|
|
3366
|
+
);
|
|
3326
3367
|
}
|
|
3327
3368
|
async function applyTags(file, tags) {
|
|
3328
3369
|
return withAudioFileSave(file, (audioFile) => {
|
|
@@ -3453,6 +3494,7 @@ async function readPictureMetadata(file) {
|
|
|
3453
3494
|
// src/simple/batch-operations.ts
|
|
3454
3495
|
init_audio_formats();
|
|
3455
3496
|
init_errors2();
|
|
3497
|
+
init_properties();
|
|
3456
3498
|
init_tag_mapping();
|
|
3457
3499
|
async function executeBatch(files, options, processor) {
|
|
3458
3500
|
if (files.length === 0) return { items: [], duration: 0 };
|
|
@@ -3500,7 +3542,7 @@ async function readTagsBatch(files, options = {}) {
|
|
|
3500
3542
|
return executeBatch(
|
|
3501
3543
|
files,
|
|
3502
3544
|
options,
|
|
3503
|
-
(audioFile) => readExtendedTag(audioFile)
|
|
3545
|
+
(audioFile) => readExtendedTag(audioFile, options.includeProperties)
|
|
3504
3546
|
);
|
|
3505
3547
|
}
|
|
3506
3548
|
async function readPropertiesBatch(files, options = {}) {
|
|
@@ -3529,7 +3571,7 @@ function extractDynamics(audioFile) {
|
|
|
3529
3571
|
if (appleSoundCheck) dynamics.appleSoundCheck = appleSoundCheck;
|
|
3530
3572
|
return Object.keys(dynamics).length > 0 ? dynamics : void 0;
|
|
3531
3573
|
}
|
|
3532
|
-
async function readMetadata(file) {
|
|
3574
|
+
async function readMetadata(file, options = {}) {
|
|
3533
3575
|
const taglib = await getTagLib();
|
|
3534
3576
|
const audioFile = await taglib.open(file);
|
|
3535
3577
|
try {
|
|
@@ -3550,7 +3592,7 @@ async function readMetadata(file) {
|
|
|
3550
3592
|
}
|
|
3551
3593
|
const dynamics = extractDynamics(audioFile);
|
|
3552
3594
|
return {
|
|
3553
|
-
tags: readExtendedTag(audioFile),
|
|
3595
|
+
tags: readExtendedTag(audioFile, options.includeProperties),
|
|
3554
3596
|
properties: audioFile.audioProperties(),
|
|
3555
3597
|
hasCoverArt: audioFile.getPictures().length > 0,
|
|
3556
3598
|
...dynamics !== void 0 ? { dynamics } : {}
|
|
@@ -3563,7 +3605,7 @@ async function readMetadataBatch(files, options = {}) {
|
|
|
3563
3605
|
return executeBatch(files, options, (audioFile) => {
|
|
3564
3606
|
const dynamics = extractDynamics(audioFile);
|
|
3565
3607
|
return {
|
|
3566
|
-
tags: readExtendedTag(audioFile),
|
|
3608
|
+
tags: readExtendedTag(audioFile, options.includeProperties),
|
|
3567
3609
|
properties: audioFile.audioProperties(),
|
|
3568
3610
|
hasCoverArt: audioFile.getPictures().length > 0,
|
|
3569
3611
|
...dynamics !== void 0 ? { dynamics } : {}
|
package/dist/index.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export { addPicture, applyCoverArt, applyPictures, applyTags, applyTagsToFile, t
|
|
|
43
43
|
export { FormatMappings, getAllProperties, getAllPropertyKeys, getPropertiesByFormat, getPropertyMetadata, isValidProperty, PROPERTIES, propertyValue, propertyValues, } from "./src/constants.js";
|
|
44
44
|
export type { PropertyMetadata } from "./src/constants/property-types.js";
|
|
45
45
|
export { copyCoverArt, exportAllPictures, exportCoverArt, exportPictureByType, findCoverArtFiles, importCoverArt, importPictureWithType, loadPictureFromFile, savePictureToFile, } from "./src/file-utils/index.js";
|
|
46
|
-
export { type AlbumDisc, type AlbumGroup, type AlbumGroupingResult, type AlbumGroupItem, type AlbumGroupKey, type AudioDynamics, type AudioFileMetadata, type DiscConfidence, type DiscFolderInfo, discFolderInfo, type DuplicateGroup, exportFolderMetadata, findDuplicates, type FolderScanItem, type FolderScanOptions, type FolderScanResult,
|
|
46
|
+
export { type AlbumDisc, type AlbumGroup, type AlbumGroupingResult, type AlbumGroupItem, type AlbumGroupKey, type AudioDynamics, type AudioFileMetadata, type DiscConfidence, type DiscFolderInfo, discFolderInfo, type DuplicateGroup, exportFolderMetadata, findDuplicates, type FolderScanItem, type FolderScanOptions, type FolderScanResult, groupAlbums, type GroupAlbumsOptions, scanFolder, scanForAlbums, type ScanForAlbumsOptions, } from "./src/folder-api/index.js";
|
|
47
47
|
export { canvasToPicture, createPictureDownloadURL, createPictureGallery, dataURLToPicture, displayPicture, imageFileToPicture, pictureToDataURL, setCoverArtFromCanvas, } from "./src/web-utils/index.js";
|
|
48
48
|
export type { AudioCodec, AudioFileInput, AudioProperties, BitrateControlMode, BroadcastAudioExtension, Chapter, ContainerFormat, ExtendedTag, FieldMapping, FileType, NamedAudioInput, OpenOptions, Picture, PictureType, PropertyMap, SetChaptersOptions, Tag, TagInput, } from "./src/types.js";
|
|
49
49
|
export { BITRATE_CONTROL_MODE_NAMES, BITRATE_CONTROL_MODE_VALUES, PICTURE_TYPE_NAMES, PICTURE_TYPE_VALUES, } from "./src/types.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,YAAY,EACV,SAAS,EACT,cAAc,GACf,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGjE,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,aAAa,EACb,wBAAwB,EACxB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,OAAO,EACL,wBAAwB,EACxB,cAAc,EACd,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,UAAU,EACV,aAAa,EACb,aAAa,EACb,SAAS,EACT,eAAe,EACf,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,aAAa,EACb,SAAS,EACT,KAAK,YAAY,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,QAAQ,EACR,aAAa,EACb,oBAAoB,EACpB,aAAa,GACd,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,aAAa,EACb,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,cAAc,EACd,KAAK,cAAc,EACnB,oBAAoB,EACpB,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -75,8 +75,7 @@ import {
|
|
|
75
75
|
findDuplicates,
|
|
76
76
|
groupAlbums,
|
|
77
77
|
scanFolder,
|
|
78
|
-
scanForAlbums
|
|
79
|
-
updateFolderTags
|
|
78
|
+
scanForAlbums
|
|
80
79
|
} from "./src/folder-api/index.js";
|
|
81
80
|
import {
|
|
82
81
|
canvasToPicture,
|
|
@@ -180,6 +179,5 @@ export {
|
|
|
180
179
|
scanFolder,
|
|
181
180
|
scanForAlbums,
|
|
182
181
|
setBufferMode,
|
|
183
|
-
setCoverArtFromCanvas
|
|
184
|
-
updateFolderTags
|
|
182
|
+
setCoverArtFromCanvas
|
|
185
183
|
};
|
package/dist/simple.browser.js
CHANGED
|
@@ -1319,6 +1319,28 @@ var init_specialized_properties = __esm({
|
|
|
1319
1319
|
mp4: "----:com.apple.iTunes:MusicBrainz Album Type"
|
|
1320
1320
|
}
|
|
1321
1321
|
},
|
|
1322
|
+
releaseCountry: {
|
|
1323
|
+
key: "RELEASECOUNTRY",
|
|
1324
|
+
description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY",
|
|
1325
|
+
type: "string",
|
|
1326
|
+
supportedFormats: [
|
|
1327
|
+
"ID3v2",
|
|
1328
|
+
"MP4",
|
|
1329
|
+
"Vorbis",
|
|
1330
|
+
"APE",
|
|
1331
|
+
"ASF",
|
|
1332
|
+
"Matroska",
|
|
1333
|
+
"WAV"
|
|
1334
|
+
],
|
|
1335
|
+
mappings: {
|
|
1336
|
+
id3v2: {
|
|
1337
|
+
frame: "TXXX",
|
|
1338
|
+
description: "MusicBrainz Album Release Country"
|
|
1339
|
+
},
|
|
1340
|
+
vorbis: "RELEASECOUNTRY",
|
|
1341
|
+
mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country"
|
|
1342
|
+
}
|
|
1343
|
+
},
|
|
1322
1344
|
itunesAdvisory: {
|
|
1323
1345
|
key: "ITUNESADVISORY",
|
|
1324
1346
|
description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here",
|
|
@@ -2697,8 +2719,9 @@ var init_mirror_fields = __esm({
|
|
|
2697
2719
|
});
|
|
2698
2720
|
|
|
2699
2721
|
// src/utils/tag-mapping.ts
|
|
2700
|
-
function readExtendedTag(audioFile) {
|
|
2701
|
-
const
|
|
2722
|
+
function readExtendedTag(audioFile, includeProperties) {
|
|
2723
|
+
const props = audioFile.properties();
|
|
2724
|
+
const tag = mapPropertiesToExtendedTag(props);
|
|
2702
2725
|
const pictures = audioFile.getPictures();
|
|
2703
2726
|
if (pictures.length > 0) tag.pictures = pictures;
|
|
2704
2727
|
const ratings = audioFile.getRatings();
|
|
@@ -2713,6 +2736,18 @@ function readExtendedTag(audioFile) {
|
|
|
2713
2736
|
if (bextData !== void 0) tag.bextData = bextData;
|
|
2714
2737
|
const ixml = audioFile.getIxml();
|
|
2715
2738
|
if (ixml !== void 0) tag.ixml = ixml;
|
|
2739
|
+
if (includeProperties !== void 0 && includeProperties.length > 0) {
|
|
2740
|
+
const extraProperties = {};
|
|
2741
|
+
for (const wireKey of includeProperties) {
|
|
2742
|
+
const values = props[fromTagLibKey(wireKey)]?.filter((v) => v !== "");
|
|
2743
|
+
if (values !== void 0 && values.length > 0) {
|
|
2744
|
+
extraProperties[wireKey] = values;
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
if (Object.keys(extraProperties).length > 0) {
|
|
2748
|
+
tag.extraProperties = extraProperties;
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2716
2751
|
return tag;
|
|
2717
2752
|
}
|
|
2718
2753
|
function mapPropertiesToExtendedTag(props) {
|
|
@@ -2776,14 +2811,16 @@ function mapPropertiesToExtendedTag(props) {
|
|
|
2776
2811
|
}
|
|
2777
2812
|
return tag;
|
|
2778
2813
|
}
|
|
2779
|
-
function
|
|
2780
|
-
const currentProps = file.properties();
|
|
2814
|
+
function mergeTagUpdatesInto(currentProps, tags) {
|
|
2781
2815
|
const newProps = normalizeTagInput(tags);
|
|
2782
2816
|
reconcilePairFields(currentProps, newProps, tags);
|
|
2783
2817
|
if (newProps.date !== void 0 || newProps.year !== void 0) {
|
|
2784
2818
|
currentProps.YEAR = [];
|
|
2785
2819
|
}
|
|
2786
|
-
|
|
2820
|
+
return { ...currentProps, ...newProps };
|
|
2821
|
+
}
|
|
2822
|
+
function mergeTagUpdates(file, tags) {
|
|
2823
|
+
file.setProperties(mergeTagUpdatesInto(file.properties(), tags));
|
|
2787
2824
|
}
|
|
2788
2825
|
function reconcilePairFields(currentProps, newProps, input) {
|
|
2789
2826
|
const pairs = [
|
|
@@ -2832,6 +2869,7 @@ function normalizeTagInput(input) {
|
|
|
2832
2869
|
}
|
|
2833
2870
|
for (const [field, val] of Object.entries(input)) {
|
|
2834
2871
|
if (BASIC_FIELDS.has(field) || val === void 0) continue;
|
|
2872
|
+
if (field === "extraProperties") continue;
|
|
2835
2873
|
if (field === "compilation") {
|
|
2836
2874
|
props[field] = [val ? "1" : "0"];
|
|
2837
2875
|
} else if (field === "advisory") {
|
|
@@ -2898,7 +2936,7 @@ var VERSION;
|
|
|
2898
2936
|
var init_version = __esm({
|
|
2899
2937
|
"src/version.ts"() {
|
|
2900
2938
|
"use strict";
|
|
2901
|
-
VERSION = "2.1
|
|
2939
|
+
VERSION = "2.2.1";
|
|
2902
2940
|
}
|
|
2903
2941
|
});
|
|
2904
2942
|
|
|
@@ -3247,8 +3285,11 @@ async function withAudioFileSaveToFile(file, fn) {
|
|
|
3247
3285
|
}
|
|
3248
3286
|
|
|
3249
3287
|
// src/simple/tag-operations.ts
|
|
3250
|
-
async function readTags(file) {
|
|
3251
|
-
return withAudioFile(
|
|
3288
|
+
async function readTags(file, options = {}) {
|
|
3289
|
+
return withAudioFile(
|
|
3290
|
+
file,
|
|
3291
|
+
(audioFile) => readExtendedTag(audioFile, options.includeProperties)
|
|
3292
|
+
);
|
|
3252
3293
|
}
|
|
3253
3294
|
async function applyTags(file, tags) {
|
|
3254
3295
|
return withAudioFileSave(file, (audioFile) => {
|
|
@@ -3379,6 +3420,7 @@ async function readPictureMetadata(file) {
|
|
|
3379
3420
|
// src/simple/batch-operations.ts
|
|
3380
3421
|
init_audio_formats();
|
|
3381
3422
|
init_errors2();
|
|
3423
|
+
init_properties();
|
|
3382
3424
|
init_tag_mapping();
|
|
3383
3425
|
async function executeBatch(files, options, processor) {
|
|
3384
3426
|
if (files.length === 0) return { items: [], duration: 0 };
|
|
@@ -3426,7 +3468,7 @@ async function readTagsBatch(files, options = {}) {
|
|
|
3426
3468
|
return executeBatch(
|
|
3427
3469
|
files,
|
|
3428
3470
|
options,
|
|
3429
|
-
(audioFile) => readExtendedTag(audioFile)
|
|
3471
|
+
(audioFile) => readExtendedTag(audioFile, options.includeProperties)
|
|
3430
3472
|
);
|
|
3431
3473
|
}
|
|
3432
3474
|
async function readPropertiesBatch(files, options = {}) {
|
|
@@ -3455,7 +3497,7 @@ function extractDynamics(audioFile) {
|
|
|
3455
3497
|
if (appleSoundCheck) dynamics.appleSoundCheck = appleSoundCheck;
|
|
3456
3498
|
return Object.keys(dynamics).length > 0 ? dynamics : void 0;
|
|
3457
3499
|
}
|
|
3458
|
-
async function readMetadata(file) {
|
|
3500
|
+
async function readMetadata(file, options = {}) {
|
|
3459
3501
|
const taglib = await getTagLib();
|
|
3460
3502
|
const audioFile = await taglib.open(file);
|
|
3461
3503
|
try {
|
|
@@ -3476,7 +3518,7 @@ async function readMetadata(file) {
|
|
|
3476
3518
|
}
|
|
3477
3519
|
const dynamics = extractDynamics(audioFile);
|
|
3478
3520
|
return {
|
|
3479
|
-
tags: readExtendedTag(audioFile),
|
|
3521
|
+
tags: readExtendedTag(audioFile, options.includeProperties),
|
|
3480
3522
|
properties: audioFile.audioProperties(),
|
|
3481
3523
|
hasCoverArt: audioFile.getPictures().length > 0,
|
|
3482
3524
|
...dynamics !== void 0 ? { dynamics } : {}
|
|
@@ -3489,13 +3531,69 @@ async function readMetadataBatch(files, options = {}) {
|
|
|
3489
3531
|
return executeBatch(files, options, (audioFile) => {
|
|
3490
3532
|
const dynamics = extractDynamics(audioFile);
|
|
3491
3533
|
return {
|
|
3492
|
-
tags: readExtendedTag(audioFile),
|
|
3534
|
+
tags: readExtendedTag(audioFile, options.includeProperties),
|
|
3493
3535
|
properties: audioFile.audioProperties(),
|
|
3494
3536
|
hasCoverArt: audioFile.getPictures().length > 0,
|
|
3495
3537
|
...dynamics !== void 0 ? { dynamics } : {}
|
|
3496
3538
|
};
|
|
3497
3539
|
});
|
|
3498
3540
|
}
|
|
3541
|
+
function entryPath(entry) {
|
|
3542
|
+
return typeof entry === "string" ? entry : entry.path;
|
|
3543
|
+
}
|
|
3544
|
+
async function executeWriteBatch(entries, options, writer) {
|
|
3545
|
+
if (entries.length === 0) return { items: [], duration: 0 };
|
|
3546
|
+
await getTagLib();
|
|
3547
|
+
const startTime = Date.now();
|
|
3548
|
+
const { concurrency = 4, continueOnError = true, onProgress, signal } = options;
|
|
3549
|
+
const items = new Array(entries.length);
|
|
3550
|
+
let processed = 0;
|
|
3551
|
+
const total = entries.length;
|
|
3552
|
+
for (let i = 0; i < entries.length; i += concurrency) {
|
|
3553
|
+
signal?.throwIfAborted();
|
|
3554
|
+
const chunk = entries.slice(i, i + concurrency);
|
|
3555
|
+
const chunkPromises = chunk.map(async (entry, idx) => {
|
|
3556
|
+
const index = i + idx;
|
|
3557
|
+
const path = entryPath(entry);
|
|
3558
|
+
try {
|
|
3559
|
+
await writer(path);
|
|
3560
|
+
items[index] = { status: "ok", path, data: void 0 };
|
|
3561
|
+
} catch (error) {
|
|
3562
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
3563
|
+
items[index] = { status: "error", path, error: err };
|
|
3564
|
+
if (!continueOnError) throw err;
|
|
3565
|
+
}
|
|
3566
|
+
processed++;
|
|
3567
|
+
onProgress?.(processed, total, path);
|
|
3568
|
+
});
|
|
3569
|
+
await Promise.all(chunkPromises);
|
|
3570
|
+
}
|
|
3571
|
+
return { items, duration: Date.now() - startTime };
|
|
3572
|
+
}
|
|
3573
|
+
async function writeTagsBatch(updates, options = {}) {
|
|
3574
|
+
const byPath = new Map(updates.map((u) => [u.path, u]));
|
|
3575
|
+
return executeWriteBatch(
|
|
3576
|
+
updates,
|
|
3577
|
+
options,
|
|
3578
|
+
(path) => withAudioFileSaveToFile(path, (audioFile) => {
|
|
3579
|
+
const update = byPath.get(path);
|
|
3580
|
+
const merged = update.tags !== void 0 ? mergeTagUpdatesInto(audioFile.properties(), update.tags) : audioFile.properties();
|
|
3581
|
+
if (update.properties !== void 0) {
|
|
3582
|
+
for (const [key, values] of Object.entries(update.properties)) {
|
|
3583
|
+
merged[fromTagLibKey(key)] = values;
|
|
3584
|
+
}
|
|
3585
|
+
}
|
|
3586
|
+
audioFile.setProperties(merged);
|
|
3587
|
+
})
|
|
3588
|
+
);
|
|
3589
|
+
}
|
|
3590
|
+
async function editTagsBatch(files, mutator, options = {}) {
|
|
3591
|
+
return executeWriteBatch(
|
|
3592
|
+
files,
|
|
3593
|
+
options,
|
|
3594
|
+
(path) => withAudioFileSaveToFile(path, (audioFile) => mutator(audioFile, path))
|
|
3595
|
+
);
|
|
3596
|
+
}
|
|
3499
3597
|
|
|
3500
3598
|
// src/simple/index.ts
|
|
3501
3599
|
init_types2();
|
|
@@ -3509,6 +3607,7 @@ export {
|
|
|
3509
3607
|
applyTagsToFile,
|
|
3510
3608
|
clearPictures,
|
|
3511
3609
|
clearTags,
|
|
3610
|
+
editTagsBatch,
|
|
3512
3611
|
findPictureByType,
|
|
3513
3612
|
getTagLib,
|
|
3514
3613
|
isValidAudioFile,
|
|
@@ -3523,5 +3622,6 @@ export {
|
|
|
3523
3622
|
readTags,
|
|
3524
3623
|
readTagsBatch,
|
|
3525
3624
|
replacePictureByType,
|
|
3526
|
-
setBufferMode
|
|
3625
|
+
setBufferMode,
|
|
3626
|
+
writeTagsBatch
|
|
3527
3627
|
};
|
|
@@ -311,6 +311,20 @@ export declare const PROPERTIES: {
|
|
|
311
311
|
readonly mp4: "----:com.apple.iTunes:MusicBrainz Album Type";
|
|
312
312
|
};
|
|
313
313
|
};
|
|
314
|
+
readonly releaseCountry: {
|
|
315
|
+
readonly key: "RELEASECOUNTRY";
|
|
316
|
+
readonly description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY";
|
|
317
|
+
readonly type: "string";
|
|
318
|
+
readonly supportedFormats: readonly ["ID3v2", "MP4", "Vorbis", "APE", "ASF", "Matroska", "WAV"];
|
|
319
|
+
readonly mappings: {
|
|
320
|
+
readonly id3v2: {
|
|
321
|
+
readonly frame: "TXXX";
|
|
322
|
+
readonly description: "MusicBrainz Album Release Country";
|
|
323
|
+
};
|
|
324
|
+
readonly vorbis: "RELEASECOUNTRY";
|
|
325
|
+
readonly mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country";
|
|
326
|
+
};
|
|
327
|
+
};
|
|
314
328
|
readonly itunesAdvisory: {
|
|
315
329
|
readonly key: "ITUNESADVISORY";
|
|
316
330
|
readonly description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../../../src/constants/properties.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,eAAO,MAAM,UAAU
|
|
1
|
+
{"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../../../src/constants/properties.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKb,CAAC;AAEX;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,UAAU,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,IAC7C,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,QAAQ,GAAG,MAAM,GAClD,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,QAAQ,GAAG,MAAM,GACtD,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,SAAS,GAAG,OAAO,GACxD,MAAM,CAAC;AAkDb,mGAAmG;AACnG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAsDD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAOzE;AAED,mGAAmG;AACnG,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GACrB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CASnB;AAGD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -73,6 +73,20 @@ export declare const SPECIALIZED_PROPERTIES: {
|
|
|
73
73
|
readonly mp4: "----:com.apple.iTunes:MusicBrainz Album Type";
|
|
74
74
|
};
|
|
75
75
|
};
|
|
76
|
+
readonly releaseCountry: {
|
|
77
|
+
readonly key: "RELEASECOUNTRY";
|
|
78
|
+
readonly description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY";
|
|
79
|
+
readonly type: "string";
|
|
80
|
+
readonly supportedFormats: readonly ["ID3v2", "MP4", "Vorbis", "APE", "ASF", "Matroska", "WAV"];
|
|
81
|
+
readonly mappings: {
|
|
82
|
+
readonly id3v2: {
|
|
83
|
+
readonly frame: "TXXX";
|
|
84
|
+
readonly description: "MusicBrainz Album Release Country";
|
|
85
|
+
};
|
|
86
|
+
readonly vorbis: "RELEASECOUNTRY";
|
|
87
|
+
readonly mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country";
|
|
88
|
+
};
|
|
89
|
+
};
|
|
76
90
|
readonly itunesAdvisory: {
|
|
77
91
|
readonly key: "ITUNESADVISORY";
|
|
78
92
|
readonly description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specialized-properties.d.ts","sourceRoot":"","sources":["../../../src/constants/specialized-properties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"specialized-properties.d.ts","sourceRoot":"","sources":["../../../src/constants/specialized-properties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+MjC;;;;;;;;OAQG;;;;;;;;;;;;;;;CAYK,CAAC"}
|
|
@@ -62,6 +62,28 @@ const SPECIALIZED_PROPERTIES = {
|
|
|
62
62
|
mp4: "----:com.apple.iTunes:MusicBrainz Album Type"
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
|
+
releaseCountry: {
|
|
66
|
+
key: "RELEASECOUNTRY",
|
|
67
|
+
description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY",
|
|
68
|
+
type: "string",
|
|
69
|
+
supportedFormats: [
|
|
70
|
+
"ID3v2",
|
|
71
|
+
"MP4",
|
|
72
|
+
"Vorbis",
|
|
73
|
+
"APE",
|
|
74
|
+
"ASF",
|
|
75
|
+
"Matroska",
|
|
76
|
+
"WAV"
|
|
77
|
+
],
|
|
78
|
+
mappings: {
|
|
79
|
+
id3v2: {
|
|
80
|
+
frame: "TXXX",
|
|
81
|
+
description: "MusicBrainz Album Release Country"
|
|
82
|
+
},
|
|
83
|
+
vorbis: "RELEASECOUNTRY",
|
|
84
|
+
mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
65
87
|
itunesAdvisory: {
|
|
66
88
|
key: "ITUNESADVISORY",
|
|
67
89
|
description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here",
|
|
@@ -1,35 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Folder-level operations:
|
|
2
|
+
* Folder-level operations: duplicates, metadata export
|
|
3
3
|
*/
|
|
4
|
-
import type {
|
|
5
|
-
import type { DuplicateGroup, FolderScanOptions, FolderUpdateResult } from "./types.js";
|
|
6
|
-
/**
|
|
7
|
-
* Update metadata for multiple files in a folder
|
|
8
|
-
*
|
|
9
|
-
* @param updates - Array of objects containing path and tags to update
|
|
10
|
-
* @param options - Update options
|
|
11
|
-
* @returns Results of the update operation
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* const updates = [
|
|
16
|
-
* { path: "/music/song1.mp3", tags: { artist: "New Artist" } },
|
|
17
|
-
* { path: "/music/song2.mp3", tags: { album: "New Album" } }
|
|
18
|
-
* ];
|
|
19
|
-
*
|
|
20
|
-
* const result = await updateFolderTags(updates);
|
|
21
|
-
* const updated = result.items.filter((i) => i.status === "ok").length;
|
|
22
|
-
* console.log(`Updated ${updated} files`);
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export declare function updateFolderTags(updates: Array<{
|
|
26
|
-
path: string;
|
|
27
|
-
tags: Partial<TagInput>;
|
|
28
|
-
}>, options?: {
|
|
29
|
-
continueOnError?: boolean;
|
|
30
|
-
concurrency?: number;
|
|
31
|
-
signal?: AbortSignal;
|
|
32
|
-
}): Promise<FolderUpdateResult>;
|
|
4
|
+
import type { DuplicateGroup, FolderScanOptions } from "./types.js";
|
|
33
5
|
/**
|
|
34
6
|
* Find duplicate audio files based on metadata
|
|
35
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"folder-operations.d.ts","sourceRoot":"","sources":["../../../src/folder-api/folder-operations.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"folder-operations.d.ts","sourceRoot":"","sources":["../../../src/folder-api/folder-operations.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAEV,cAAc,EACd,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAiBpB;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,cAAc,EAAE,CAAC,CAuB3B;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAoBf"}
|
|
@@ -1,39 +1,5 @@
|
|
|
1
|
-
import { applyTagsToFile } from "../simple/index.js";
|
|
2
1
|
import { writeFileData } from "../utils/write.js";
|
|
3
|
-
import { processBatch } from "./file-processors.js";
|
|
4
2
|
import { scanFolder } from "./scan-operations.js";
|
|
5
|
-
import { EMPTY_TAG } from "./types.js";
|
|
6
|
-
async function updateFolderTags(updates, options = {}) {
|
|
7
|
-
const startTime = Date.now();
|
|
8
|
-
const { continueOnError = true, concurrency = 4, signal } = options;
|
|
9
|
-
const items = [];
|
|
10
|
-
const batchSize = concurrency * 10;
|
|
11
|
-
for (let i = 0; i < updates.length; i += batchSize) {
|
|
12
|
-
signal?.throwIfAborted();
|
|
13
|
-
const batch = updates.slice(i, Math.min(i + batchSize, updates.length));
|
|
14
|
-
const updateMap = new Map(batch.map((u) => [u.path, u]));
|
|
15
|
-
await processBatch(
|
|
16
|
-
batch.map((u) => u.path),
|
|
17
|
-
async (path) => {
|
|
18
|
-
const update = updateMap.get(path);
|
|
19
|
-
try {
|
|
20
|
-
await applyTagsToFile(update.path, update.tags);
|
|
21
|
-
items.push({ status: "ok", path: update.path });
|
|
22
|
-
} catch (error) {
|
|
23
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
24
|
-
if (continueOnError) {
|
|
25
|
-
items.push({ status: "error", path: update.path, error: err });
|
|
26
|
-
} else {
|
|
27
|
-
throw err;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return { path, tags: EMPTY_TAG };
|
|
31
|
-
},
|
|
32
|
-
concurrency
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
return { items, duration: Date.now() - startTime };
|
|
36
|
-
}
|
|
37
3
|
function buildCriteriaKey(tags, criteria) {
|
|
38
4
|
const record = {};
|
|
39
5
|
for (const field of criteria) {
|
|
@@ -84,6 +50,5 @@ async function exportFolderMetadata(folderPath, outputPath, options) {
|
|
|
84
50
|
}
|
|
85
51
|
export {
|
|
86
52
|
exportFolderMetadata,
|
|
87
|
-
findDuplicates
|
|
88
|
-
updateFolderTags
|
|
53
|
+
findDuplicates
|
|
89
54
|
};
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Batch folder operations for TagLib-Wasm
|
|
3
3
|
* Provides APIs for scanning directories and processing multiple audio files
|
|
4
4
|
*/
|
|
5
|
-
export type { AudioDynamics, AudioFileMetadata, DuplicateGroup, FolderScanItem, FolderScanOptions, FolderScanResult,
|
|
5
|
+
export type { AudioDynamics, AudioFileMetadata, DuplicateGroup, FolderScanItem, FolderScanOptions, FolderScanResult, } from "./types.js";
|
|
6
6
|
export { scanFolder } from "./scan-operations.js";
|
|
7
|
-
export { exportFolderMetadata, findDuplicates
|
|
7
|
+
export { exportFolderMetadata, findDuplicates } from "./folder-operations.js";
|
|
8
8
|
export { type AlbumDisc, type AlbumGroup, type AlbumGroupingResult, type AlbumGroupItem, type AlbumGroupKey, type DiscConfidence, type DiscFolderInfo, discFolderInfo, groupAlbums, type GroupAlbumsOptions, } from "./group-albums.js";
|
|
9
9
|
export { scanForAlbums, type ScanForAlbumsOptions } from "./scan-for-albums.js";
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/folder-api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/folder-api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,EACL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,cAAc,EACd,WAAW,EACX,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { scanFolder } from "./scan-operations.js";
|
|
2
|
-
import {
|
|
3
|
-
exportFolderMetadata,
|
|
4
|
-
findDuplicates,
|
|
5
|
-
updateFolderTags
|
|
6
|
-
} from "./folder-operations.js";
|
|
2
|
+
import { exportFolderMetadata, findDuplicates } from "./folder-operations.js";
|
|
7
3
|
import {
|
|
8
4
|
discFolderInfo,
|
|
9
5
|
groupAlbums
|
|
@@ -15,6 +11,5 @@ export {
|
|
|
15
11
|
findDuplicates,
|
|
16
12
|
groupAlbums,
|
|
17
13
|
scanFolder,
|
|
18
|
-
scanForAlbums
|
|
19
|
-
updateFolderTags
|
|
14
|
+
scanForAlbums
|
|
20
15
|
};
|