@marcmeese/n8n-nodes-mediatranscriber 0.0.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/LICENSE.md +19 -0
- package/README.md +46 -0
- package/dist/credentials/MediaTranscriberApi.credentials.d.ts +10 -0
- package/dist/credentials/MediaTranscriberApi.credentials.js +46 -0
- package/dist/credentials/MediaTranscriberApi.credentials.js.map +1 -0
- package/dist/credentials/marcmeeselogo.png +0 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/nodes/MediaTranscriber/DeleteJob/DeleteJob.node.d.ts +5 -0
- package/dist/nodes/MediaTranscriber/DeleteJob/DeleteJob.node.js +34 -0
- package/dist/nodes/MediaTranscriber/DeleteJob/DeleteJob.node.js.map +1 -0
- package/dist/nodes/MediaTranscriber/DeleteJob/marcmeeselogo.png +0 -0
- package/dist/nodes/MediaTranscriber/GetJob/GetJob.node.d.ts +5 -0
- package/dist/nodes/MediaTranscriber/GetJob/GetJob.node.js +32 -0
- package/dist/nodes/MediaTranscriber/GetJob/GetJob.node.js.map +1 -0
- package/dist/nodes/MediaTranscriber/GetJob/marcmeeselogo.png +0 -0
- package/dist/nodes/MediaTranscriber/GetTranscript/GetTranscript.node.d.ts +5 -0
- package/dist/nodes/MediaTranscriber/GetTranscript/GetTranscript.node.js +59 -0
- package/dist/nodes/MediaTranscriber/GetTranscript/GetTranscript.node.js.map +1 -0
- package/dist/nodes/MediaTranscriber/GetTranscript/marcmeeselogo.png +0 -0
- package/dist/nodes/MediaTranscriber/Transcribe/Transcribe.node.d.ts +5 -0
- package/dist/nodes/MediaTranscriber/Transcribe/Transcribe.node.js +192 -0
- package/dist/nodes/MediaTranscriber/Transcribe/Transcribe.node.js.map +1 -0
- package/dist/nodes/MediaTranscriber/Transcribe/marcmeeselogo.png +0 -0
- package/dist/nodes/MediaTranscriber/jobId.d.ts +3 -0
- package/dist/nodes/MediaTranscriber/jobId.js +13 -0
- package/dist/nodes/MediaTranscriber/jobId.js.map +1 -0
- package/dist/utils/errors.d.ts +16 -0
- package/dist/utils/errors.js +72 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/execute.d.ts +6 -0
- package/dist/utils/execute.js +26 -0
- package/dist/utils/execute.js.map +1 -0
- package/dist/utils/files.d.ts +5 -0
- package/dist/utils/files.js +47 -0
- package/dist/utils/files.js.map +1 -0
- package/dist/utils/input.d.ts +13 -0
- package/dist/utils/input.js +48 -0
- package/dist/utils/input.js.map +1 -0
- package/dist/utils/jobRequest.d.ts +13 -0
- package/dist/utils/jobRequest.js +36 -0
- package/dist/utils/jobRequest.js.map +1 -0
- package/dist/utils/jobs.d.ts +3 -0
- package/dist/utils/jobs.js +12 -0
- package/dist/utils/jobs.js.map +1 -0
- package/dist/utils/multipart.d.ts +20 -0
- package/dist/utils/multipart.js +36 -0
- package/dist/utils/multipart.js.map +1 -0
- package/dist/utils/polling.d.ts +11 -0
- package/dist/utils/polling.js +25 -0
- package/dist/utils/polling.js.map +1 -0
- package/dist/utils/request.d.ts +17 -0
- package/dist/utils/request.js +41 -0
- package/dist/utils/request.js.map +1 -0
- package/dist/utils/transcriptFlow.d.ts +17 -0
- package/dist/utils/transcriptFlow.js +67 -0
- package/dist/utils/transcriptFlow.js.map +1 -0
- package/dist/utils/url.d.ts +4 -0
- package/dist/utils/url.js +10 -0
- package/dist/utils/url.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeBody = decodeBody;
|
|
4
|
+
exports.describeApiError = describeApiError;
|
|
5
|
+
exports.extractHttpError = extractHttpError;
|
|
6
|
+
/**
|
|
7
|
+
* Liest den Body einer Fehler-Antwort (JSON, String, Buffer oder ArrayBuffer) als Objekt oder String.
|
|
8
|
+
*/
|
|
9
|
+
function decodeBody(body) {
|
|
10
|
+
let text;
|
|
11
|
+
if (typeof body === 'string')
|
|
12
|
+
text = body;
|
|
13
|
+
else if (body instanceof ArrayBuffer)
|
|
14
|
+
text = Buffer.from(body).toString('utf8');
|
|
15
|
+
else if (Buffer.isBuffer(body))
|
|
16
|
+
text = body.toString('utf8');
|
|
17
|
+
if (text === undefined)
|
|
18
|
+
return body;
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(text);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return text;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Baut eine lesbare Fehlermeldung aus einer MediaTranscriber-Fehlerantwort.
|
|
28
|
+
* FastAPI liefert {"detail": "..."} bzw. bei Validierungsfehlern {"detail": [{"loc", "msg"}]}.
|
|
29
|
+
*/
|
|
30
|
+
function describeApiError(body) {
|
|
31
|
+
const decoded = decodeBody(body);
|
|
32
|
+
if (typeof decoded === 'string')
|
|
33
|
+
return decoded.trim() || undefined;
|
|
34
|
+
if (!decoded || typeof decoded !== 'object')
|
|
35
|
+
return undefined;
|
|
36
|
+
const detail = decoded.detail;
|
|
37
|
+
if (typeof detail === 'string')
|
|
38
|
+
return detail;
|
|
39
|
+
if (Array.isArray(detail)) {
|
|
40
|
+
const messages = detail
|
|
41
|
+
.map((entry) => {
|
|
42
|
+
const { loc, msg } = (entry !== null && entry !== void 0 ? entry : {});
|
|
43
|
+
const field = Array.isArray(loc) ? loc.filter((p) => p !== 'body').join('.') : '';
|
|
44
|
+
return typeof msg === 'string' ? (field ? `${field}: ${msg}` : msg) : undefined;
|
|
45
|
+
})
|
|
46
|
+
.filter(Boolean);
|
|
47
|
+
if (messages.length)
|
|
48
|
+
return messages.join('; ');
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Sucht HTTP-Status und Response-Body in den verschiedenen Fehlerformen von n8n/axios.
|
|
54
|
+
*/
|
|
55
|
+
function extractHttpError(error) {
|
|
56
|
+
var _a;
|
|
57
|
+
const candidates = [error];
|
|
58
|
+
const e = error;
|
|
59
|
+
if (e && typeof e === 'object')
|
|
60
|
+
candidates.push(e.cause, e.context);
|
|
61
|
+
for (const c of candidates) {
|
|
62
|
+
if (!c || typeof c !== 'object')
|
|
63
|
+
continue;
|
|
64
|
+
const response = c.response;
|
|
65
|
+
if (response && typeof response === 'object') {
|
|
66
|
+
return { status: response.status, body: (_a = response.data) !== null && _a !== void 0 ? _a : response.body };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const httpCode = Number(e === null || e === void 0 ? void 0 : e.httpCode);
|
|
70
|
+
return { status: Number.isFinite(httpCode) && httpCode > 0 ? httpCode : undefined };
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
|
2
|
+
/**
|
|
3
|
+
* Führt `handler` für jedes Eingabe-Item aus, setzt pairedItem und behandelt
|
|
4
|
+
* "Continue On Fail" einheitlich für alle Nodes.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runPerItem(ctx: IExecuteFunctions, handler: (itemIndex: number) => Promise<INodeExecutionData>): Promise<INodeExecutionData[][]>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runPerItem = runPerItem;
|
|
4
|
+
/**
|
|
5
|
+
* Führt `handler` für jedes Eingabe-Item aus, setzt pairedItem und behandelt
|
|
6
|
+
* "Continue On Fail" einheitlich für alle Nodes.
|
|
7
|
+
*/
|
|
8
|
+
async function runPerItem(ctx, handler) {
|
|
9
|
+
const items = ctx.getInputData();
|
|
10
|
+
const out = [];
|
|
11
|
+
for (let i = 0; i < items.length; i++) {
|
|
12
|
+
try {
|
|
13
|
+
const result = await handler(i);
|
|
14
|
+
out.push({ ...result, pairedItem: { item: i } });
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
if (ctx.continueOnFail()) {
|
|
18
|
+
out.push({ json: { error: error.message }, pairedItem: { item: i } });
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return [out];
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=execute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/utils/execute.ts"],"names":[],"mappings":";;AAMA,gCAoBC;AAxBD;;;GAGG;AACI,KAAK,UAAU,UAAU,CAC/B,GAAsB,EACtB,OAA2D;IAE3D,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;IACjC,MAAM,GAAG,GAAyB,EAAE,CAAC;IAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;YAChC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC1B,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjF,SAAS;YACV,CAAC;YACD,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function mimeTypeFor(fileName: string): string;
|
|
2
|
+
/** Dateiname ohne Endung, als Basis für die Namen der Transkript-Dateien. */
|
|
3
|
+
export declare function baseName(fileName: string): string;
|
|
4
|
+
/** Basisname aus einer Medien-URL (letztes Pfadsegment), Fallback "transcript". */
|
|
5
|
+
export declare function baseNameFromUrl(url: string): string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mimeTypeFor = mimeTypeFor;
|
|
4
|
+
exports.baseName = baseName;
|
|
5
|
+
exports.baseNameFromUrl = baseNameFromUrl;
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const MIME_TYPES = {
|
|
8
|
+
mp3: 'audio/mpeg',
|
|
9
|
+
wav: 'audio/wav',
|
|
10
|
+
m4a: 'audio/mp4',
|
|
11
|
+
aac: 'audio/aac',
|
|
12
|
+
flac: 'audio/flac',
|
|
13
|
+
ogg: 'audio/ogg',
|
|
14
|
+
oga: 'audio/ogg',
|
|
15
|
+
opus: 'audio/opus',
|
|
16
|
+
webm: 'video/webm',
|
|
17
|
+
mp4: 'video/mp4',
|
|
18
|
+
m4v: 'video/x-m4v',
|
|
19
|
+
mkv: 'video/x-matroska',
|
|
20
|
+
mov: 'video/quicktime',
|
|
21
|
+
avi: 'video/x-msvideo',
|
|
22
|
+
txt: 'text/plain',
|
|
23
|
+
srt: 'application/x-subrip',
|
|
24
|
+
json: 'application/json',
|
|
25
|
+
};
|
|
26
|
+
function mimeTypeFor(fileName) {
|
|
27
|
+
var _a;
|
|
28
|
+
return (_a = MIME_TYPES[(0, path_1.extname)(fileName).slice(1).toLowerCase()]) !== null && _a !== void 0 ? _a : 'application/octet-stream';
|
|
29
|
+
}
|
|
30
|
+
/** Dateiname ohne Endung, als Basis für die Namen der Transkript-Dateien. */
|
|
31
|
+
function baseName(fileName) {
|
|
32
|
+
const name = fileName.replace(/^.*[\\/]/, '');
|
|
33
|
+
const ext = (0, path_1.extname)(name);
|
|
34
|
+
return (ext ? name.slice(0, -ext.length) : name) || 'transcript';
|
|
35
|
+
}
|
|
36
|
+
/** Basisname aus einer Medien-URL (letztes Pfadsegment), Fallback "transcript". */
|
|
37
|
+
function baseNameFromUrl(url) {
|
|
38
|
+
var _a;
|
|
39
|
+
try {
|
|
40
|
+
const segment = decodeURIComponent((_a = new URL(url).pathname.split('/').filter(Boolean).pop()) !== null && _a !== void 0 ? _a : '');
|
|
41
|
+
return segment ? baseName(segment) : 'transcript';
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return 'transcript';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":";;AAsBA,kCAEC;AAGD,4BAIC;AAGD,0CAOC;AAzCD,+BAA+B;AAE/B,MAAM,UAAU,GAA2B;IAC1C,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,kBAAkB;IACvB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,sBAAsB;IAC3B,IAAI,EAAE,kBAAkB;CACxB,CAAC;AAEF,SAAgB,WAAW,CAAC,QAAgB;;IAC3C,OAAO,MAAA,UAAU,CAAC,IAAA,cAAO,EAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,mCAAI,0BAA0B,CAAC;AAC3F,CAAC;AAED,6EAA6E;AAC7E,SAAgB,QAAQ,CAAC,QAAgB;IACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,IAAA,cAAO,EAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC;AAClE,CAAC;AAED,mFAAmF;AACnF,SAAgB,eAAe,CAAC,GAAW;;IAC1C,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAA,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,mCAAI,EAAE,CAAC,CAAC;QACjG,OAAO,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,YAAY,CAAC;IACrB,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Readable } from 'stream';
|
|
2
|
+
import type { IExecuteFunctions } from 'n8n-workflow';
|
|
3
|
+
export interface InputFile {
|
|
4
|
+
fileName: string;
|
|
5
|
+
contentType: string;
|
|
6
|
+
size: number;
|
|
7
|
+
content: Buffer | Readable;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Liest die Mediendatei eines Items – aus einer Binary-Property oder von einem lokalen
|
|
11
|
+
* Pfad im Container. Gestreamt, wo möglich, damit große Videos nicht im Speicher landen.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getInputFile(this: IExecuteFunctions, itemIndex: number, inputMode: 'binary' | 'path'): Promise<InputFile>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getInputFile = getInputFile;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
7
|
+
const files_1 = require("./files");
|
|
8
|
+
/**
|
|
9
|
+
* Liest die Mediendatei eines Items – aus einer Binary-Property oder von einem lokalen
|
|
10
|
+
* Pfad im Container. Gestreamt, wo möglich, damit große Videos nicht im Speicher landen.
|
|
11
|
+
*/
|
|
12
|
+
async function getInputFile(itemIndex, inputMode) {
|
|
13
|
+
var _a;
|
|
14
|
+
if (inputMode === 'path') {
|
|
15
|
+
const filePath = this.getNodeParameter('filePath', itemIndex).trim();
|
|
16
|
+
let stat;
|
|
17
|
+
try {
|
|
18
|
+
stat = await fs_1.promises.stat(filePath);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Datei nicht gefunden: ${filePath}`, { itemIndex });
|
|
22
|
+
}
|
|
23
|
+
if (!stat.isFile()) {
|
|
24
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Kein regulärer Dateipfad: ${filePath}`, { itemIndex });
|
|
25
|
+
}
|
|
26
|
+
const fileName = (0, path_1.basename)(filePath);
|
|
27
|
+
return { fileName, contentType: (0, files_1.mimeTypeFor)(fileName), size: stat.size, content: (0, fs_1.createReadStream)(filePath) };
|
|
28
|
+
}
|
|
29
|
+
const propertyName = this.getNodeParameter('binaryPropertyName', itemIndex);
|
|
30
|
+
const binaryData = this.helpers.assertBinaryData(itemIndex, propertyName);
|
|
31
|
+
const fileName = binaryData.fileName || `media.${(_a = binaryData.fileExtension) !== null && _a !== void 0 ? _a : 'bin'}`;
|
|
32
|
+
const contentType = binaryData.mimeType || (0, files_1.mimeTypeFor)(fileName);
|
|
33
|
+
// Im Filesystem-/S3-Modus von n8n liegt die Datei nicht im Speicher: dann streamen
|
|
34
|
+
if (binaryData.id) {
|
|
35
|
+
const metadata = await this.helpers.getBinaryMetadata(binaryData.id);
|
|
36
|
+
if (typeof metadata.fileSize === 'number') {
|
|
37
|
+
return {
|
|
38
|
+
fileName,
|
|
39
|
+
contentType,
|
|
40
|
+
size: metadata.fileSize,
|
|
41
|
+
content: await this.helpers.getBinaryStream(binaryData.id),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const buffer = await this.helpers.getBinaryDataBuffer(itemIndex, propertyName);
|
|
46
|
+
return { fileName, contentType, size: buffer.length, content: buffer };
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/utils/input.ts"],"names":[],"mappings":";;AAoBA,oCAuCC;AA3DD,2BAAsD;AACtD,+BAAgC;AAIhC,+CAAkD;AAElD,mCAAsC;AAStC;;;GAGG;AACI,KAAK,UAAU,YAAY,CAEjC,SAAiB,EACjB,SAA4B;;IAE5B,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAI,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAY,CAAC,IAAI,EAAE,CAAC;QACjF,IAAI,IAAI,CAAC;QACT,IAAI,CAAC;YACJ,IAAI,GAAG,MAAM,aAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACR,MAAM,IAAI,iCAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,yBAAyB,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAClG,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACpB,MAAM,IAAI,iCAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,6BAA6B,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,MAAM,QAAQ,GAAG,IAAA,eAAQ,EAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAA,mBAAW,EAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAA,qBAAgB,EAAC,QAAQ,CAAC,EAAE,CAAC;IAC/G,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,SAAS,CAAW,CAAC;IACtF,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,IAAI,SAAS,MAAA,UAAU,CAAC,aAAa,mCAAI,KAAK,EAAE,CAAC;IACrF,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,IAAI,IAAA,mBAAW,EAAC,QAAQ,CAAC,CAAC;IAEjE,mFAAmF;IACnF,IAAI,UAAU,CAAC,EAAE,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACrE,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC3C,OAAO;gBACN,QAAQ;gBACR,WAAW;gBACX,IAAI,EAAE,QAAQ,CAAC,QAAQ;gBACvB,OAAO,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;aAC1D,CAAC;QACH,CAAC;IACF,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC/E,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IDataObject } from 'n8n-workflow';
|
|
2
|
+
export interface TranscribeOptions {
|
|
3
|
+
language?: string;
|
|
4
|
+
diarize?: boolean;
|
|
5
|
+
callbackUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Formularfelder für POST /v1/jobs (Upload). Nur gesetzte Werte werden gesendet:
|
|
9
|
+
* leere Sprache = Server-Default, diarize nur als Abschalten (Server kann es nur deaktivieren).
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildUploadFields(options: TranscribeOptions): Array<[string, string]>;
|
|
12
|
+
/** JSON-Body für POST /v1/jobs/url mit denselben Regeln wie der Upload. */
|
|
13
|
+
export declare function buildUrlBody(url: string, options: TranscribeOptions): IDataObject;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildUploadFields = buildUploadFields;
|
|
4
|
+
exports.buildUrlBody = buildUrlBody;
|
|
5
|
+
/**
|
|
6
|
+
* Formularfelder für POST /v1/jobs (Upload). Nur gesetzte Werte werden gesendet:
|
|
7
|
+
* leere Sprache = Server-Default, diarize nur als Abschalten (Server kann es nur deaktivieren).
|
|
8
|
+
*/
|
|
9
|
+
function buildUploadFields(options) {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
const fields = [];
|
|
12
|
+
const language = ((_a = options.language) !== null && _a !== void 0 ? _a : '').trim();
|
|
13
|
+
const callbackUrl = ((_b = options.callbackUrl) !== null && _b !== void 0 ? _b : '').trim();
|
|
14
|
+
if (language)
|
|
15
|
+
fields.push(['language', language]);
|
|
16
|
+
if (options.diarize === false)
|
|
17
|
+
fields.push(['diarize', 'false']);
|
|
18
|
+
if (callbackUrl)
|
|
19
|
+
fields.push(['callback_url', callbackUrl]);
|
|
20
|
+
return fields;
|
|
21
|
+
}
|
|
22
|
+
/** JSON-Body für POST /v1/jobs/url mit denselben Regeln wie der Upload. */
|
|
23
|
+
function buildUrlBody(url, options) {
|
|
24
|
+
var _a, _b;
|
|
25
|
+
const body = { url: url.trim() };
|
|
26
|
+
const language = ((_a = options.language) !== null && _a !== void 0 ? _a : '').trim();
|
|
27
|
+
const callbackUrl = ((_b = options.callbackUrl) !== null && _b !== void 0 ? _b : '').trim();
|
|
28
|
+
if (language)
|
|
29
|
+
body.language = language;
|
|
30
|
+
if (options.diarize === false)
|
|
31
|
+
body.diarize = false;
|
|
32
|
+
if (callbackUrl)
|
|
33
|
+
body.callback_url = callbackUrl;
|
|
34
|
+
return body;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=jobRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobRequest.js","sourceRoot":"","sources":["../../src/utils/jobRequest.ts"],"names":[],"mappings":";;AAYA,8CAQC;AAGD,oCAQC;AAvBD;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,OAA0B;;IAC3D,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,CAAC,MAAA,OAAO,CAAC,QAAQ,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,MAAM,WAAW,GAAG,CAAC,MAAA,OAAO,CAAC,WAAW,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,IAAI,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClD,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK;QAAE,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IACjE,IAAI,WAAW;QAAE,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC;AACf,CAAC;AAED,2EAA2E;AAC3E,SAAgB,YAAY,CAAC,GAAW,EAAE,OAA0B;;IACnE,MAAM,IAAI,GAAgB,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAG,CAAC,MAAA,OAAO,CAAC,QAAQ,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,MAAM,WAAW,GAAG,CAAC,MAAA,OAAO,CAAC,WAAW,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,IAAI,QAAQ;QAAE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACvC,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK;QAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACpD,IAAI,WAAW;QAAE,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;IACjD,OAAO,IAAI,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.jobPath = jobPath;
|
|
4
|
+
exports.getJob = getJob;
|
|
5
|
+
const request_1 = require("./request");
|
|
6
|
+
function jobPath(jobId, suffix = '') {
|
|
7
|
+
return `/v1/jobs/${encodeURIComponent(jobId.trim())}${suffix}`;
|
|
8
|
+
}
|
|
9
|
+
async function getJob(jobId) {
|
|
10
|
+
return request_1.apiRequest.call(this, { method: 'GET', path: jobPath(jobId) });
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/utils/jobs.ts"],"names":[],"mappings":";;AAIA,0BAEC;AAED,wBAEC;AARD,uCAAuC;AAEvC,SAAgB,OAAO,CAAC,KAAa,EAAE,MAAM,GAAG,EAAE;IACjD,OAAO,YAAY,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;AAChE,CAAC;AAEM,KAAK,UAAU,MAAM,CAA0B,KAAa;IAClE,OAAO,oBAAU,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Readable } from 'stream';
|
|
2
|
+
export interface MultipartFile {
|
|
3
|
+
fieldName: string;
|
|
4
|
+
fileName: string;
|
|
5
|
+
contentType: string;
|
|
6
|
+
/** Größe in Bytes – nötig für den Content-Length-Header */
|
|
7
|
+
size: number;
|
|
8
|
+
content: Buffer | Readable;
|
|
9
|
+
}
|
|
10
|
+
export interface MultipartBody {
|
|
11
|
+
body: Readable;
|
|
12
|
+
contentType: string;
|
|
13
|
+
contentLength: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Baut einen multipart/form-data-Body als Stream (Datei wird nicht komplett in den
|
|
17
|
+
* Speicher geladen) inkl. exakter Content-Length. n8n reicht Streams mit eigenem
|
|
18
|
+
* Content-Type unverändert an axios durch.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildMultipart(fields: Array<[string, string]>, file: MultipartFile, boundary?: string): MultipartBody;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildMultipart = buildMultipart;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const stream_1 = require("stream");
|
|
6
|
+
/** Entfernt Zeichen, die einen Multipart-Header aufbrechen würden. */
|
|
7
|
+
function headerValue(value) {
|
|
8
|
+
return value.replace(/[\r\n]/g, ' ').replace(/"/g, '%22');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Baut einen multipart/form-data-Body als Stream (Datei wird nicht komplett in den
|
|
12
|
+
* Speicher geladen) inkl. exakter Content-Length. n8n reicht Streams mit eigenem
|
|
13
|
+
* Content-Type unverändert an axios durch.
|
|
14
|
+
*/
|
|
15
|
+
function buildMultipart(fields, file, boundary = `----n8nFormBoundary${(0, crypto_1.randomBytes)(12).toString('hex')}`) {
|
|
16
|
+
const head = Buffer.from(fields
|
|
17
|
+
.map(([name, value]) => `--${boundary}\r\nContent-Disposition: form-data; name="${headerValue(name)}"\r\n\r\n${value}\r\n`)
|
|
18
|
+
.join('') +
|
|
19
|
+
`--${boundary}\r\nContent-Disposition: form-data; name="${headerValue(file.fieldName)}"; ` +
|
|
20
|
+
`filename="${headerValue(file.fileName)}"\r\nContent-Type: ${file.contentType}\r\n\r\n`, 'utf8');
|
|
21
|
+
const tail = Buffer.from(`\r\n--${boundary}--\r\n`, 'utf8');
|
|
22
|
+
async function* chunks() {
|
|
23
|
+
yield head;
|
|
24
|
+
if (Buffer.isBuffer(file.content))
|
|
25
|
+
yield file.content;
|
|
26
|
+
else
|
|
27
|
+
yield* file.content;
|
|
28
|
+
yield tail;
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
body: stream_1.Readable.from(chunks(), { objectMode: false }),
|
|
32
|
+
contentType: `multipart/form-data; boundary=${boundary}`,
|
|
33
|
+
contentLength: head.length + file.size + tail.length,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=multipart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart.js","sourceRoot":"","sources":["../../src/utils/multipart.ts"],"names":[],"mappings":";;AA4BA,wCA8BC;AA1DD,mCAAqC;AACrC,mCAAkC;AAiBlC,sEAAsE;AACtE,SAAS,WAAW,CAAC,KAAa;IACjC,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,SAAgB,cAAc,CAC7B,MAA+B,EAC/B,IAAmB,EACnB,QAAQ,GAAG,sBAAsB,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;IAElE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CACvB,MAAM;SACJ,GAAG,CACH,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CACjB,KAAK,QAAQ,6CAA6C,WAAW,CAAC,IAAI,CAAC,YAAY,KAAK,MAAM,CACnG;SACA,IAAI,CAAC,EAAE,CAAC;QACT,KAAK,QAAQ,6CAA6C,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK;QAC1F,aAAa,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,sBAAsB,IAAI,CAAC,WAAW,UAAU,EACxF,MAAM,CACN,CAAC;IACF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,QAAQ,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE5D,KAAK,SAAS,CAAC,CAAC,MAAM;QACrB,MAAM,IAAI,CAAC;QACX,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC;;YACjD,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QACzB,MAAM,IAAI,CAAC;IACZ,CAAC;IAED,OAAO;QACN,IAAI,EAAE,iBAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QACpD,WAAW,EAAE,iCAAiC,QAAQ,EAAE;QACxD,aAAa,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM;KACpD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type StatusClass = 'success' | 'failed' | 'pending';
|
|
2
|
+
/** Ordnet einen MediaTranscriber-Jobstatus ein (queued → downloading → extracting → transcribing → done | error). */
|
|
3
|
+
export declare function classifyJobStatus(status: unknown): StatusClass;
|
|
4
|
+
/** Fehlermeldung für einen fehlgeschlagenen Job aus der Status-Antwort. */
|
|
5
|
+
export declare function describeFailedJob(job: unknown): string;
|
|
6
|
+
export type TranscriptFormat = 'json' | 'txt' | 'srt';
|
|
7
|
+
export declare const TRANSCRIPT_FILES: Record<Exclude<TranscriptFormat, 'json'>, {
|
|
8
|
+
extension: string;
|
|
9
|
+
mimeType: string;
|
|
10
|
+
property: string;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TRANSCRIPT_FILES = void 0;
|
|
4
|
+
exports.classifyJobStatus = classifyJobStatus;
|
|
5
|
+
exports.describeFailedJob = describeFailedJob;
|
|
6
|
+
/** Ordnet einen MediaTranscriber-Jobstatus ein (queued → downloading → extracting → transcribing → done | error). */
|
|
7
|
+
function classifyJobStatus(status) {
|
|
8
|
+
const value = String(status !== null && status !== void 0 ? status : '').toLowerCase();
|
|
9
|
+
if (value === 'done')
|
|
10
|
+
return 'success';
|
|
11
|
+
if (value === 'error')
|
|
12
|
+
return 'failed';
|
|
13
|
+
return 'pending';
|
|
14
|
+
}
|
|
15
|
+
/** Fehlermeldung für einen fehlgeschlagenen Job aus der Status-Antwort. */
|
|
16
|
+
function describeFailedJob(job) {
|
|
17
|
+
const { id, error_reason: reason, error_detail: detail } = (job !== null && job !== void 0 ? job : {});
|
|
18
|
+
const parts = [reason, detail].filter((p) => typeof p === 'string' && p).join(' – ');
|
|
19
|
+
return `Transkription ${String(id !== null && id !== void 0 ? id : '?')} fehlgeschlagen${parts ? `: ${parts}` : ''}`;
|
|
20
|
+
}
|
|
21
|
+
exports.TRANSCRIPT_FILES = {
|
|
22
|
+
txt: { extension: 'txt', mimeType: 'text/plain', property: 'transcript_txt' },
|
|
23
|
+
srt: { extension: 'srt', mimeType: 'application/x-subrip', property: 'transcript_srt' },
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=polling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polling.js","sourceRoot":"","sources":["../../src/utils/polling.ts"],"names":[],"mappings":";;;AAGA,8CAKC;AAGD,8CAIC;AAbD,qHAAqH;AACrH,SAAgB,iBAAiB,CAAC,MAAe;IAChD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,aAAN,MAAM,cAAN,MAAM,GAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACjD,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IACvC,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC;IACvC,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,2EAA2E;AAC3E,SAAgB,iBAAiB,CAAC,GAAY;IAC7C,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,EAAE,CAA4B,CAAC;IAClG,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrF,OAAO,iBAAiB,MAAM,CAAC,EAAE,aAAF,EAAE,cAAF,EAAE,GAAI,GAAG,CAAC,kBAAkB,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACxF,CAAC;AAIY,QAAA,gBAAgB,GAAyG;IACrI,GAAG,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE;IAC7E,GAAG,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,sBAAsB,EAAE,QAAQ,EAAE,gBAAgB,EAAE;CACvF,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IDataObject, IExecuteFunctions, IHttpRequestMethods, IHttpRequestOptions } from 'n8n-workflow';
|
|
2
|
+
export declare const CREDENTIAL_NAME = "mediaTranscriberApi";
|
|
3
|
+
export interface ApiRequestOptions {
|
|
4
|
+
method: IHttpRequestMethods;
|
|
5
|
+
path: string;
|
|
6
|
+
body?: IHttpRequestOptions['body'];
|
|
7
|
+
headers?: IDataObject;
|
|
8
|
+
qs?: IDataObject;
|
|
9
|
+
/** Antwort als Buffer statt JSON (für Datei-Downloads) */
|
|
10
|
+
binary?: boolean;
|
|
11
|
+
returnFullResponse?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Authentifizierter Request gegen die MediaTranscriber API. Fehler werden als NodeApiError
|
|
15
|
+
* mit der Fehlermeldung und der Meldung aus der Antwort geworfen.
|
|
16
|
+
*/
|
|
17
|
+
export declare function apiRequest(this: IExecuteFunctions, options: ApiRequestOptions): Promise<any>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CREDENTIAL_NAME = void 0;
|
|
4
|
+
exports.apiRequest = apiRequest;
|
|
5
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
6
|
+
const errors_1 = require("./errors");
|
|
7
|
+
const url_1 = require("./url");
|
|
8
|
+
exports.CREDENTIAL_NAME = 'mediaTranscriberApi';
|
|
9
|
+
/**
|
|
10
|
+
* Authentifizierter Request gegen die MediaTranscriber API. Fehler werden als NodeApiError
|
|
11
|
+
* mit der Fehlermeldung und der Meldung aus der Antwort geworfen.
|
|
12
|
+
*/
|
|
13
|
+
async function apiRequest(options) {
|
|
14
|
+
var _a;
|
|
15
|
+
const credentials = await this.getCredentials(exports.CREDENTIAL_NAME);
|
|
16
|
+
const request = {
|
|
17
|
+
method: options.method,
|
|
18
|
+
url: (0, url_1.joinUrl)(credentials.baseUrl, options.path),
|
|
19
|
+
headers: options.headers,
|
|
20
|
+
qs: options.qs,
|
|
21
|
+
body: options.body,
|
|
22
|
+
returnFullResponse: options.returnFullResponse,
|
|
23
|
+
};
|
|
24
|
+
if (options.binary)
|
|
25
|
+
request.encoding = 'arraybuffer';
|
|
26
|
+
else
|
|
27
|
+
request.json = true;
|
|
28
|
+
try {
|
|
29
|
+
return await this.helpers.httpRequestWithAuthentication.call(this, exports.CREDENTIAL_NAME, request);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
const { status, body } = (0, errors_1.extractHttpError)(error);
|
|
33
|
+
const detail = (_a = (0, errors_1.describeApiError)(body)) !== null && _a !== void 0 ? _a : error.message;
|
|
34
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error, {
|
|
35
|
+
message: status ? `MediaTranscriber antwortete mit HTTP ${status}: ${detail}` : `MediaTranscriber nicht erreichbar: ${detail}`,
|
|
36
|
+
description: detail,
|
|
37
|
+
httpCode: status ? String(status) : undefined,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/utils/request.ts"],"names":[],"mappings":";;;AA6BA,gCAwBC;AA9CD,+CAA4C;AAE5C,qCAA8D;AAC9D,+BAAgC;AAEnB,QAAA,eAAe,GAAG,qBAAqB,CAAC;AAarD;;;GAGG;AACI,KAAK,UAAU,UAAU,CAA0B,OAA0B;;IACnF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,uBAAe,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAwB;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,GAAG,EAAE,IAAA,aAAO,EAAC,WAAW,CAAC,OAAiB,EAAE,OAAO,CAAC,IAAI,CAAC;QACzD,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;KAC9C,CAAC;IACF,IAAI,OAAO,CAAC,MAAM;QAAE,OAAO,CAAC,QAAQ,GAAG,aAAa,CAAC;;QAChD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAEzB,IAAI,CAAC;QACJ,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,6BAA6B,CAAC,IAAI,CAAC,IAAI,EAAE,uBAAe,EAAE,OAAO,CAAC,CAAC;IAC9F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAA,yBAAgB,EAAC,KAAK,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAA,IAAA,yBAAgB,EAAC,IAAI,CAAC,mCAAK,KAAe,CAAC,OAAO,CAAC;QAClE,MAAM,IAAI,2BAAY,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAmB,EAAE;YAC3D,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,wCAAwC,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,sCAAsC,MAAM,EAAE;YAC9H,WAAW,EAAE,MAAM;YACnB,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;SAC7C,CAAC,CAAC;IACJ,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IBinaryData, IDataObject, IExecuteFunctions } from 'n8n-workflow';
|
|
2
|
+
import type { TranscriptFormat } from './polling';
|
|
3
|
+
/**
|
|
4
|
+
* Fragt den Status ab, bis der Job fertig ist. Wirft bei Status "error" und bei
|
|
5
|
+
* Zeitüberschreitung (der Job läuft dann serverseitig weiter).
|
|
6
|
+
*/
|
|
7
|
+
export declare function waitForJob(this: IExecuteFunctions, jobId: string, pollIntervalSeconds: number, timeoutSeconds: number, itemIndex: number): Promise<IDataObject>;
|
|
8
|
+
/** Transkript als JSON-Objekt (language, duration, text, segments[]). */
|
|
9
|
+
export declare function fetchTranscriptJson(this: IExecuteFunctions, jobId: string): Promise<IDataObject>;
|
|
10
|
+
/** Transkript als TXT- oder SRT-Datei. */
|
|
11
|
+
export declare function fetchTranscriptFile(this: IExecuteFunctions, jobId: string, format: Exclude<TranscriptFormat, 'json'>, baseName: string): Promise<IBinaryData>;
|
|
12
|
+
/** Holt alle gewünschten Formate eines fertigen Jobs. */
|
|
13
|
+
export declare function fetchTranscriptOutputs(this: IExecuteFunctions, jobId: string, formats: TranscriptFormat[], baseName: string): Promise<{
|
|
14
|
+
transcript?: IDataObject;
|
|
15
|
+
binary: Record<string, IBinaryData>;
|
|
16
|
+
}>;
|
|
17
|
+
export declare function deleteJob(this: IExecuteFunctions, jobId: string): Promise<void>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.waitForJob = waitForJob;
|
|
4
|
+
exports.fetchTranscriptJson = fetchTranscriptJson;
|
|
5
|
+
exports.fetchTranscriptFile = fetchTranscriptFile;
|
|
6
|
+
exports.fetchTranscriptOutputs = fetchTranscriptOutputs;
|
|
7
|
+
exports.deleteJob = deleteJob;
|
|
8
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
9
|
+
const jobs_1 = require("./jobs");
|
|
10
|
+
const polling_1 = require("./polling");
|
|
11
|
+
const request_1 = require("./request");
|
|
12
|
+
/**
|
|
13
|
+
* Fragt den Status ab, bis der Job fertig ist. Wirft bei Status "error" und bei
|
|
14
|
+
* Zeitüberschreitung (der Job läuft dann serverseitig weiter).
|
|
15
|
+
*/
|
|
16
|
+
async function waitForJob(jobId, pollIntervalSeconds, timeoutSeconds, itemIndex) {
|
|
17
|
+
const deadline = Date.now() + timeoutSeconds * 1000;
|
|
18
|
+
for (;;) {
|
|
19
|
+
const job = await jobs_1.getJob.call(this, jobId);
|
|
20
|
+
const state = (0, polling_1.classifyJobStatus)(job.status);
|
|
21
|
+
if (state === 'success')
|
|
22
|
+
return job;
|
|
23
|
+
if (state === 'failed') {
|
|
24
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), (0, polling_1.describeFailedJob)(job), {
|
|
25
|
+
itemIndex,
|
|
26
|
+
description: JSON.stringify(job, null, 2),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const remaining = deadline - Date.now();
|
|
30
|
+
if (remaining <= 0) {
|
|
31
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Zeitüberschreitung nach ${timeoutSeconds}s: Job ${jobId} ist noch nicht fertig (Status ${String(job.status)}). Abrufbar mit "Get Job"/"Get Transcript".`, { itemIndex });
|
|
32
|
+
}
|
|
33
|
+
await (0, n8n_workflow_1.sleep)(Math.min(pollIntervalSeconds * 1000, remaining));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Transkript als JSON-Objekt (language, duration, text, segments[]). */
|
|
37
|
+
async function fetchTranscriptJson(jobId) {
|
|
38
|
+
return request_1.apiRequest.call(this, { method: 'GET', path: (0, jobs_1.jobPath)(jobId, '/transcript'), qs: { format: 'json' } });
|
|
39
|
+
}
|
|
40
|
+
/** Transkript als TXT- oder SRT-Datei. */
|
|
41
|
+
async function fetchTranscriptFile(jobId, format, baseName) {
|
|
42
|
+
const body = (await request_1.apiRequest.call(this, {
|
|
43
|
+
method: 'GET',
|
|
44
|
+
path: (0, jobs_1.jobPath)(jobId, '/transcript'),
|
|
45
|
+
qs: { format },
|
|
46
|
+
binary: true,
|
|
47
|
+
}));
|
|
48
|
+
const { extension, mimeType } = polling_1.TRANSCRIPT_FILES[format];
|
|
49
|
+
return this.helpers.prepareBinaryData(Buffer.from(body), `${baseName}.${extension}`, mimeType);
|
|
50
|
+
}
|
|
51
|
+
/** Holt alle gewünschten Formate eines fertigen Jobs. */
|
|
52
|
+
async function fetchTranscriptOutputs(jobId, formats, baseName) {
|
|
53
|
+
const result = { binary: {} };
|
|
54
|
+
for (const format of formats) {
|
|
55
|
+
if (format === 'json') {
|
|
56
|
+
result.transcript = await fetchTranscriptJson.call(this, jobId);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
result.binary[polling_1.TRANSCRIPT_FILES[format].property] = await fetchTranscriptFile.call(this, jobId, format, baseName);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
async function deleteJob(jobId) {
|
|
65
|
+
await request_1.apiRequest.call(this, { method: 'DELETE', path: (0, jobs_1.jobPath)(jobId) });
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=transcriptFlow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcriptFlow.js","sourceRoot":"","sources":["../../src/utils/transcriptFlow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.joinUrl = joinUrl;
|
|
4
|
+
/**
|
|
5
|
+
* Verbindet Base-URL und Pfad, egal ob die Base-URL mit "/" endet oder der Pfad mit "/" beginnt.
|
|
6
|
+
*/
|
|
7
|
+
function joinUrl(baseUrl, path) {
|
|
8
|
+
return `${baseUrl.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":";;AAGA,0BAEC;AALD;;GAEG;AACH,SAAgB,OAAO,CAAC,OAAe,EAAE,IAAY;IACpD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;AACrE,CAAC"}
|