@ai-sdk/provider-utils 5.0.11 → 5.0.13
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 +17 -0
- package/dist/index.js +47 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/detect-media-type.ts +68 -32
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @ai-sdk/provider-utils
|
|
2
2
|
|
|
3
|
+
## 5.0.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [1e2f324]
|
|
8
|
+
- @ai-sdk/provider@4.0.4
|
|
9
|
+
|
|
10
|
+
## 5.0.12
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 02ffdcb: fix(provider-utils): bound media-type sniffing decode for ID3-prefixed input
|
|
15
|
+
|
|
16
|
+
Media-type detection stripped ID3 tags before the ~18-byte prefix cap, decoding the entire base64 attachment (plus a full-size copy) whenever the data began with `ID3`/`SUQz`. This turned the intended O(1) sniff into an O(N) decode of the whole attachment. Detection now decodes at most a bounded prefix and skips the ID3 tag within that bound, keeping cost O(1) in input size on all paths (image, audio, and combined).
|
|
17
|
+
|
|
18
|
+
- 76cb673: fix: detect MP4 audio from its ftyp box during transcription
|
|
19
|
+
|
|
3
20
|
## 5.0.11
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -427,7 +427,7 @@ var documentMediaTypeSignatures = [
|
|
|
427
427
|
// %PDF
|
|
428
428
|
}
|
|
429
429
|
];
|
|
430
|
-
var
|
|
430
|
+
var audioMediaTypeSignaturesWithoutMp4 = [
|
|
431
431
|
{
|
|
432
432
|
mediaType: "audio/mpeg",
|
|
433
433
|
bytesPrefix: [255, 251]
|
|
@@ -489,15 +489,28 @@ var audioMediaTypeSignatures = [
|
|
|
489
489
|
mediaType: "audio/aac",
|
|
490
490
|
bytesPrefix: [64, 21, 0, 0]
|
|
491
491
|
},
|
|
492
|
-
{
|
|
493
|
-
mediaType: "audio/mp4",
|
|
494
|
-
bytesPrefix: [102, 116, 121, 112]
|
|
495
|
-
},
|
|
496
492
|
{
|
|
497
493
|
mediaType: "audio/webm",
|
|
498
494
|
bytesPrefix: [26, 69, 223, 163]
|
|
499
495
|
}
|
|
500
496
|
];
|
|
497
|
+
var audioMediaTypeSignatures = [
|
|
498
|
+
...audioMediaTypeSignaturesWithoutMp4,
|
|
499
|
+
{
|
|
500
|
+
mediaType: "audio/mp4",
|
|
501
|
+
bytesPrefix: [
|
|
502
|
+
0,
|
|
503
|
+
0,
|
|
504
|
+
0,
|
|
505
|
+
null,
|
|
506
|
+
102,
|
|
507
|
+
116,
|
|
508
|
+
121,
|
|
509
|
+
112
|
|
510
|
+
// ftyp
|
|
511
|
+
]
|
|
512
|
+
}
|
|
513
|
+
];
|
|
501
514
|
var videoMediaTypeSignatures = [
|
|
502
515
|
{
|
|
503
516
|
mediaType: "video/mp4",
|
|
@@ -540,25 +553,37 @@ var videoMediaTypeSignatures = [
|
|
|
540
553
|
// RIFF (AVI)
|
|
541
554
|
}
|
|
542
555
|
];
|
|
543
|
-
var
|
|
544
|
-
|
|
556
|
+
var DEFAULT_SNIFF_BYTES = 18;
|
|
557
|
+
var MAX_SIGNATURE_BYTES = 12;
|
|
558
|
+
var MAX_ID3_TAG_BYTES = 128 * 1024;
|
|
559
|
+
var ID3_SCAN_BYTES = MAX_ID3_TAG_BYTES + MAX_SIGNATURE_BYTES;
|
|
560
|
+
function decodePrefix(data, maxBytes) {
|
|
561
|
+
if (typeof data !== "string") {
|
|
562
|
+
return data.length > maxBytes ? data.subarray(0, maxBytes) : data;
|
|
563
|
+
}
|
|
564
|
+
const maxChars = Math.ceil(maxBytes / 3) * 4;
|
|
565
|
+
const bytes = convertBase64ToUint8Array(
|
|
566
|
+
data.substring(0, Math.min(data.length, maxChars))
|
|
567
|
+
);
|
|
568
|
+
return bytes.length > maxBytes ? bytes.subarray(0, maxBytes) : bytes;
|
|
569
|
+
}
|
|
570
|
+
function hasID3(bytes) {
|
|
571
|
+
return bytes.length > 10 && bytes[0] === 73 && // 'I'
|
|
572
|
+
bytes[1] === 68 && // 'D'
|
|
573
|
+
bytes[2] === 51;
|
|
574
|
+
}
|
|
575
|
+
var stripID3 = (bytes) => {
|
|
545
576
|
const id3Size = (bytes[6] & 127) << 21 | (bytes[7] & 127) << 14 | (bytes[8] & 127) << 7 | bytes[9] & 127;
|
|
546
|
-
return bytes.
|
|
577
|
+
return bytes.subarray(id3Size + 10);
|
|
547
578
|
};
|
|
548
|
-
function stripID3TagsIfPresent(data) {
|
|
549
|
-
const hasId3 = typeof data === "string" && data.startsWith("SUQz") || typeof data !== "string" && data.length > 10 && data[0] === 73 && // 'I'
|
|
550
|
-
data[1] === 68 && // 'D'
|
|
551
|
-
data[2] === 51;
|
|
552
|
-
return hasId3 ? stripID3(data) : data;
|
|
553
|
-
}
|
|
554
579
|
function detectMediaTypeBySignatures({
|
|
555
580
|
data,
|
|
556
581
|
signatures
|
|
557
582
|
}) {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
583
|
+
let bytes = decodePrefix(data, DEFAULT_SNIFF_BYTES);
|
|
584
|
+
if (hasID3(bytes)) {
|
|
585
|
+
bytes = stripID3(decodePrefix(data, ID3_SCAN_BYTES));
|
|
586
|
+
}
|
|
562
587
|
for (const signature of signatures) {
|
|
563
588
|
if (bytes.length >= signature.bytesPrefix.length && signature.bytesPrefix.every(
|
|
564
589
|
(byte, index) => byte === null || bytes[index] === byte
|
|
@@ -584,7 +609,9 @@ function detectMediaType({
|
|
|
584
609
|
signatures: [
|
|
585
610
|
...imageMediaTypeSignatures,
|
|
586
611
|
...documentMediaTypeSignatures,
|
|
587
|
-
|
|
612
|
+
// MP4 containers cannot be distinguished as audio or video by ftyp alone.
|
|
613
|
+
// Preserve the generic detection result as video/mp4.
|
|
614
|
+
...audioMediaTypeSignaturesWithoutMp4,
|
|
588
615
|
...videoMediaTypeSignatures
|
|
589
616
|
]
|
|
590
617
|
});
|
|
@@ -1153,7 +1180,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
|
|
|
1153
1180
|
}
|
|
1154
1181
|
|
|
1155
1182
|
// src/version.ts
|
|
1156
|
-
var VERSION = true ? "5.0.
|
|
1183
|
+
var VERSION = true ? "5.0.13" : "0.0.0-test";
|
|
1157
1184
|
|
|
1158
1185
|
// src/get-from-api.ts
|
|
1159
1186
|
var getOriginalFetch = () => globalThis.fetch;
|