UNPKG

@thaleslaray/n8n-nodes-elevenlabs

Version:

Nó n8n para integração com a API da ElevenLabs incluindo Speech-to-Text, Text-to-Speech e Conversational AI

356 lines (355 loc) 17.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ElevenLabsSpeechToText = void 0; const n8n_workflow_1 = require("n8n-workflow"); const utils_1 = require("../utils"); class ElevenLabsSpeechToText { constructor() { this.description = { displayName: 'ElevenLabs Speech-to-Text', name: 'elevenLabsSpeechToText', icon: 'file:../elevenlabs.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["operation"]}}', description: 'Converta áudio em texto usando a API da ElevenLabs', defaults: { name: 'ElevenLabs STT', }, inputs: ['main'], outputs: ['main'], credentials: [ { name: 'elevenLabsApi', required: true, }, ], properties: [ { displayName: 'Fonte do Áudio', name: 'audioSource', type: 'options', options: [ { name: 'Arquivo Binário', value: 'binaryFile', }, { name: 'URL', value: 'url', }, ], default: 'binaryFile', description: 'Fonte do arquivo de áudio para transcrição', }, { displayName: 'Campo Binário', name: 'binaryPropertyName', type: 'string', default: 'data', required: true, displayOptions: { show: { audioSource: ['binaryFile'], }, }, description: 'Nome do campo binário que contém o arquivo de áudio', }, { displayName: 'URL do Áudio', name: 'audioUrl', type: 'string', default: '', required: true, displayOptions: { show: { audioSource: ['url'], }, }, description: 'URL do arquivo de áudio para transcrição', }, { displayName: 'Modelo', name: 'modelId', type: 'options', options: [ { name: 'Scribe v1', value: 'scribe_v1', }, { name: 'Scribe v1 Experimental', value: 'scribe_v1_experimental', }, ], default: 'scribe_v1', description: 'O ID do modelo a ser usado para transcrição, atualmente apenas "scribe_v1" e "scribe_v1_experimental" estão disponíveis', }, { displayName: 'Opções Avançadas', name: 'advancedOptions', type: 'collection', placeholder: 'Adicionar Opção', default: {}, options: [ { displayName: 'Código de Idioma', name: 'languageCode', type: 'string', default: '', placeholder: 'pt, en, es, fr...', description: 'Código ISO-639-1 ou ISO-639-3 do idioma do áudio. Se não especificado, o idioma será detectado automaticamente.', }, { displayName: 'Diarização', name: 'diarization', type: 'boolean', default: false, description: 'Identificar diferentes falantes no áudio', }, { displayName: 'Timestamps', name: 'timestampsGranularity', type: 'options', options: [ { name: 'Nenhum', value: 'none', }, { name: 'Palavra', value: 'word', }, { name: 'Caractere', value: 'character', }, ], default: 'word', description: 'Granularidade dos timestamps no texto transcrito', }, { displayName: 'Marcar Eventos de Áudio', name: 'tagAudioEvents', type: 'boolean', default: true, description: 'Marcar eventos de áudio como (risos), (passos), etc.', }, { displayName: 'Número Máximo de Falantes', name: 'numSpeakers', type: 'number', typeOptions: { minValue: 1, maxValue: 32, }, default: 1, description: 'Número máximo de falantes no áudio (1-32)', }, { displayName: 'Formato de Arquivo', name: 'fileFormat', type: 'options', options: [ { name: 'Outro', value: 'other', }, { name: 'PCM 16-bit 16kHz', value: 'pcm_s16le_16', } ], default: 'other', description: 'O formato do áudio de entrada', }, { displayName: 'Formatos Adicionais', name: 'additionalFormats', type: 'fixedCollection', typeOptions: { multipleValues: true, }, default: {}, options: [ { displayName: 'Formato', name: 'format', values: [ { displayName: 'Tipo', name: 'format', type: 'options', options: [ { name: 'DOCX', value: 'docx', }, { name: 'HTML', value: 'html', }, { name: 'PDF', value: 'pdf', }, { name: 'JSON Segmentado', value: 'segmented_json', }, { name: 'SRT', value: 'srt', }, { name: 'TXT', value: 'txt', }, ], default: 'txt', description: 'Formato adicional para exportar a transcrição', }, { displayName: 'Incluir Falantes', name: 'include_speakers', type: 'boolean', default: false, description: 'Incluir identificação dos falantes no formato adicional', }, { displayName: 'Incluir Timestamps', name: 'include_timestamps', type: 'boolean', default: true, description: 'Incluir marcações de tempo no formato adicional', }, { displayName: 'Máximo de Caracteres por Linha', name: 'max_characters_per_line', type: 'number', default: 0, description: 'Número máximo de caracteres por linha (0 para sem limite)', }, { displayName: 'Máximo de Caracteres por Segmento', name: 'max_segment_chars', type: 'number', default: 0, description: 'Número máximo de caracteres por segmento (0 para sem limite)', }, { displayName: 'Duração Máxima do Segmento (s)', name: 'max_segment_duration_s', type: 'number', default: 0, description: 'Duração máxima de cada segmento em segundos (0 para sem limite)', }, { displayName: 'Segmentar em Silêncios Maiores que (s)', name: 'segment_on_silence_longer_than_s', type: 'number', default: 0, description: 'Criar novo segmento quando encontrar silêncio maior que X segundos (0 para desabilitar)', }, ], }, ], }, ], }, ], }; } async execute() { var _a; const items = this.getInputData(); const returnData = []; for (let i = 0; i < items.length; i++) { try { const audioSource = this.getNodeParameter('audioSource', i); const model = this.getNodeParameter('modelId', i); const advancedOptions = this.getNodeParameter('advancedOptions', i); const formData = { model_id: model, }; if (advancedOptions.languageCode) { formData.language_code = advancedOptions.languageCode; } if (advancedOptions.diarization !== undefined) { formData.diarize = advancedOptions.diarization.toString(); } if (advancedOptions.timestampsGranularity !== undefined) { formData.timestamps_granularity = advancedOptions.timestampsGranularity; } if (advancedOptions.tagAudioEvents !== undefined) { formData.tag_audio_events = advancedOptions.tagAudioEvents.toString(); } if (advancedOptions.numSpeakers !== undefined) { formData.num_speakers = advancedOptions.numSpeakers.toString(); } if (advancedOptions.fileFormat !== undefined) { formData.file_format = advancedOptions.fileFormat; } if (advancedOptions.additionalFormats) { const formats = []; for (const format of advancedOptions.additionalFormats.format) { formats.push({ format: format.format, include_speakers: format.include_speakers, include_timestamps: format.include_timestamps, max_characters_per_line: format.max_characters_per_line, max_segment_chars: format.max_segment_chars, max_segment_duration_s: format.max_segment_duration_s, segment_on_silence_longer_than_s: format.segment_on_silence_longer_than_s, }); } if (formats.length > 0) { formData.additional_formats = JSON.stringify(formats); } } const options = await utils_1.createBaseOptions.call(this, 'speech-to-text', 'POST'); const finalFormData = {}; for (const [key, value] of Object.entries(formData)) { if (typeof value === 'boolean') { finalFormData[key] = value.toString(); } else { finalFormData[key] = value; } } if (audioSource === 'binaryFile') { const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i); const binaryData = (_a = items[i].binary) === null || _a === void 0 ? void 0 : _a[binaryPropertyName]; if (!binaryData) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Nenhum dado binário encontrado'); } const buffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName); finalFormData.file = { value: buffer, options: { filename: binaryData.fileName || 'audio.mp3', contentType: binaryData.mimeType, }, }; } else { const audioUrl = this.getNodeParameter('audioUrl', i); finalFormData.cloud_storage_url = audioUrl; } options.formData = finalFormData; const response = await this.helpers.request(options); returnData.push((0, utils_1.formatReturnData)(response, i)); } catch (error) { const errorResult = utils_1.handleApiError.call(this, error, i); if (errorResult) { returnData.push(errorResult); continue; } throw error; } } return [returnData]; } } exports.ElevenLabsSpeechToText = ElevenLabsSpeechToText;