@daemux/transcription 0.4.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/.claude-plugin/plugin.json +6 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +130 -0
- package/dist/index.js.map +1 -0
- package/package.json +33 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transcription Plugin
|
|
3
|
+
* OpenAI audio transcription provider for voice messages.
|
|
4
|
+
* Registers as a TranscriptionProvider via the plugin API.
|
|
5
|
+
*/
|
|
6
|
+
import type { TranscriptionProvider, TranscriptionOptions, TranscriptionResult } from '@daemux/plugin-sdk';
|
|
7
|
+
export type { TranscriptionProvider, TranscriptionOptions, TranscriptionResult } from '@daemux/plugin-sdk';
|
|
8
|
+
export declare class OpenAITranscriptionProvider implements TranscriptionProvider {
|
|
9
|
+
readonly id = "openai";
|
|
10
|
+
private apiKey;
|
|
11
|
+
private baseUrl;
|
|
12
|
+
constructor(config: {
|
|
13
|
+
apiKey: string;
|
|
14
|
+
baseUrl?: string;
|
|
15
|
+
});
|
|
16
|
+
transcribe(audio: Buffer, fileName: string, options?: TranscriptionOptions): Promise<TranscriptionResult>;
|
|
17
|
+
private fetchWithRetry;
|
|
18
|
+
}
|
|
19
|
+
export declare function createTranscriptionProvider(config: {
|
|
20
|
+
apiKey: string;
|
|
21
|
+
baseUrl?: string;
|
|
22
|
+
}): TranscriptionProvider;
|
|
23
|
+
export declare const manifest: {
|
|
24
|
+
name: string;
|
|
25
|
+
version: string;
|
|
26
|
+
description: string;
|
|
27
|
+
author: string;
|
|
28
|
+
};
|
|
29
|
+
declare const _default: {
|
|
30
|
+
manifest: {
|
|
31
|
+
name: string;
|
|
32
|
+
version: string;
|
|
33
|
+
description: string;
|
|
34
|
+
author: string;
|
|
35
|
+
};
|
|
36
|
+
createTranscriptionProvider: typeof createTranscriptionProvider;
|
|
37
|
+
};
|
|
38
|
+
export default _default;
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE3G,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAwB3G,qBAAa,2BAA4B,YAAW,qBAAqB;IACvE,QAAQ,CAAC,EAAE,YAAY;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAKlD,UAAU,CACd,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC;YAcjB,cAAc;CAqD7B;AAiDD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,qBAAqB,CAEvB;AAMD,eAAO,MAAM,QAAQ;;;;;CAKpB,CAAC;;;;;;;;;;AAEF,wBAAyD"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transcription Plugin
|
|
3
|
+
* OpenAI audio transcription provider for voice messages.
|
|
4
|
+
* Registers as a TranscriptionProvider via the plugin API.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Response Validation Schema
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
const TranscriptionResultSchema = z.object({
|
|
11
|
+
text: z.string(),
|
|
12
|
+
language: z.string().optional(),
|
|
13
|
+
duration: z.number().optional(),
|
|
14
|
+
});
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Retry Configuration
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
const RETRYABLE_STATUSES = [429, 500, 502, 503];
|
|
19
|
+
const MAX_RETRIES = 3;
|
|
20
|
+
const BASE_DELAY_MS = 1000;
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// OpenAI Transcription Provider
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
export class OpenAITranscriptionProvider {
|
|
25
|
+
id = 'openai';
|
|
26
|
+
apiKey;
|
|
27
|
+
baseUrl;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.apiKey = config.apiKey;
|
|
30
|
+
this.baseUrl = config.baseUrl ?? 'https://api.openai.com/v1';
|
|
31
|
+
}
|
|
32
|
+
async transcribe(audio, fileName, options) {
|
|
33
|
+
const model = options?.model ?? 'gpt-4o-transcribe';
|
|
34
|
+
const responseFormat = options?.responseFormat ?? 'json';
|
|
35
|
+
const normalizedFileName = normalizeAudioExtension(fileName);
|
|
36
|
+
const response = await this.fetchWithRetry(audio, normalizedFileName, model, responseFormat, options);
|
|
37
|
+
if (responseFormat === 'text') {
|
|
38
|
+
return { text: await response.text() };
|
|
39
|
+
}
|
|
40
|
+
return TranscriptionResultSchema.parse(await response.json());
|
|
41
|
+
}
|
|
42
|
+
async fetchWithRetry(audio, fileName, model, responseFormat, options) {
|
|
43
|
+
let lastError;
|
|
44
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
45
|
+
if (attempt > 0) {
|
|
46
|
+
const delay = BASE_DELAY_MS * Math.pow(2, attempt - 1);
|
|
47
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
48
|
+
}
|
|
49
|
+
const formData = new FormData();
|
|
50
|
+
const mimeType = resolveAudioMimeType(fileName);
|
|
51
|
+
formData.append('file', new Blob([audio], { type: mimeType }), fileName);
|
|
52
|
+
formData.append('model', model);
|
|
53
|
+
formData.append('response_format', responseFormat);
|
|
54
|
+
if (options?.language) {
|
|
55
|
+
formData.append('language', options.language);
|
|
56
|
+
}
|
|
57
|
+
const response = await fetch(`${this.baseUrl}/audio/transcriptions`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
60
|
+
body: formData,
|
|
61
|
+
signal: AbortSignal.timeout(120_000),
|
|
62
|
+
});
|
|
63
|
+
if (response.ok) {
|
|
64
|
+
return response;
|
|
65
|
+
}
|
|
66
|
+
if (attempt < MAX_RETRIES && RETRYABLE_STATUSES.includes(response.status)) {
|
|
67
|
+
lastError = new Error(`Transcription failed (${response.status}), retrying (${attempt + 1}/${MAX_RETRIES})`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const errorText = await response.text().catch(() => 'unknown error');
|
|
71
|
+
throw new Error(`Transcription failed (${response.status}): ${errorText}`);
|
|
72
|
+
}
|
|
73
|
+
throw lastError ?? new Error('Transcription failed after retries');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Audio Extension Normalization
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
const EXTENSION_MAP = {
|
|
80
|
+
'.oga': '.ogg',
|
|
81
|
+
'.opus': '.ogg',
|
|
82
|
+
'.wma': '.mp3',
|
|
83
|
+
'.aac': '.m4a',
|
|
84
|
+
'.3gp': '.mp4',
|
|
85
|
+
};
|
|
86
|
+
function normalizeAudioExtension(fileName) {
|
|
87
|
+
const dotIndex = fileName.lastIndexOf('.');
|
|
88
|
+
if (dotIndex === -1)
|
|
89
|
+
return `${fileName}.ogg`;
|
|
90
|
+
const ext = fileName.slice(dotIndex).toLowerCase();
|
|
91
|
+
const mapped = EXTENSION_MAP[ext];
|
|
92
|
+
if (!mapped)
|
|
93
|
+
return fileName;
|
|
94
|
+
return fileName.slice(0, dotIndex) + mapped;
|
|
95
|
+
}
|
|
96
|
+
const MIME_MAP = {
|
|
97
|
+
'.ogg': 'audio/ogg',
|
|
98
|
+
'.mp3': 'audio/mpeg',
|
|
99
|
+
'.wav': 'audio/wav',
|
|
100
|
+
'.flac': 'audio/flac',
|
|
101
|
+
'.m4a': 'audio/mp4',
|
|
102
|
+
'.mp4': 'audio/mp4',
|
|
103
|
+
'.webm': 'audio/webm',
|
|
104
|
+
'.mpga': 'audio/mpeg',
|
|
105
|
+
'.mpeg': 'audio/mpeg',
|
|
106
|
+
};
|
|
107
|
+
function resolveAudioMimeType(fileName) {
|
|
108
|
+
const dotIndex = fileName.lastIndexOf('.');
|
|
109
|
+
if (dotIndex === -1)
|
|
110
|
+
return 'audio/ogg';
|
|
111
|
+
const ext = fileName.slice(dotIndex).toLowerCase();
|
|
112
|
+
return MIME_MAP[ext] ?? 'application/octet-stream';
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Factory
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
export function createTranscriptionProvider(config) {
|
|
118
|
+
return new OpenAITranscriptionProvider(config);
|
|
119
|
+
}
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Plugin Manifest & Lifecycle
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
export const manifest = {
|
|
124
|
+
name: '@daemux/transcription',
|
|
125
|
+
version: '1.0.0',
|
|
126
|
+
description: 'OpenAI audio transcription provider for daemux',
|
|
127
|
+
author: 'daemux',
|
|
128
|
+
};
|
|
129
|
+
export default { manifest, createTranscriptionProvider };
|
|
130
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAChD,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E,MAAM,OAAO,2BAA2B;IAC7B,EAAE,GAAG,QAAQ,CAAC;IACf,MAAM,CAAS;IACf,OAAO,CAAS;IAExB,YAAY,MAA4C;QACtD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,2BAA2B,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,UAAU,CACd,KAAa,EACb,QAAgB,EAChB,OAA8B;QAE9B,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,mBAAmB,CAAC;QACpD,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,MAAM,CAAC;QACzD,MAAM,kBAAkB,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QAE7D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAEtG,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;YAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QACzC,CAAC;QAED,OAAO,yBAAyB,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAEO,KAAK,CAAC,cAAc,CAC1B,KAAa,EACb,QAAgB,EAChB,KAAa,EACb,cAAsB,EACtB,OAA8B;QAE9B,IAAI,SAA4B,CAAC;QAEjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;YACxD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAChB,MAAM,KAAK,GAAG,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;gBACvD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YAC7D,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAChD,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;YACzE,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAChC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;YACnD,IAAI,OAAO,EAAE,QAAQ,EAAE,CAAC;gBACtB,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YAChD,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,GAAG,IAAI,CAAC,OAAO,uBAAuB,EACtC;gBACE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE;gBACnD,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;aACrC,CACF,CAAC;YAEF,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,IAAI,OAAO,GAAG,WAAW,IAAI,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1E,SAAS,GAAG,IAAI,KAAK,CACnB,yBAAyB,QAAQ,CAAC,MAAM,gBAAgB,OAAO,GAAG,CAAC,IAAI,WAAW,GAAG,CACtF,CAAC;gBACF,SAAS;YACX,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;YACrE,MAAM,IAAI,KAAK,CACb,yBAAyB,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAC1D,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACrE,CAAC;CACF;AAED,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E,MAAM,aAAa,GAA2B;IAC5C,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,MAAM;CACf,CAAC;AAEF,SAAS,uBAAuB,CAAC,QAAgB;IAC/C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,GAAG,QAAQ,MAAM,CAAC;IAE9C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAE7B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC;AAC9C,CAAC;AAED,MAAM,QAAQ,GAA2B;IACvC,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,YAAY;CACtB,CAAC;AAEF,SAAS,oBAAoB,CAAC,QAAgB;IAC5C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IAExC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,0BAA0B,CAAC;AACrD,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,UAAU,2BAA2B,CACzC,MAA4C;IAE5C,OAAO,IAAI,2BAA2B,CAAC,MAAM,CAAC,CAAC;AACjD,CAAC;AAED,8EAA8E;AAC9E,8BAA8B;AAC9B,8EAA8E;AAE9E,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,uBAAuB;IAC7B,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,gDAAgD;IAC7D,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEF,eAAe,EAAE,QAAQ,EAAE,2BAA2B,EAAE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@daemux/transcription",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "OpenAI audio transcription provider for voice messages",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": ["dist", ".claude-plugin"],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsc --watch",
|
|
12
|
+
"clean": "rm -rf dist",
|
|
13
|
+
"typecheck": "tsc --noEmit"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@daemux/plugin-sdk": "^0.5.0",
|
|
17
|
+
"zod": "^3.24.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^22.0.0",
|
|
21
|
+
"typescript": "^5.9.0"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/daemux/daemux-plugins.git",
|
|
29
|
+
"directory": "features/transcription"
|
|
30
|
+
},
|
|
31
|
+
"keywords": ["daemux", "transcription", "plugin"],
|
|
32
|
+
"license": "MIT"
|
|
33
|
+
}
|