ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const config = require('../config');
|
||||
const { ASRProviderFactory } = require('./providers/asrProviders');
|
||||
|
||||
class SpeechToTextService {
|
||||
constructor() {
|
||||
this.tempDir = path.join(__dirname, '../temp');
|
||||
this.ensureTempDirectory();
|
||||
|
||||
// Initialize ASR provider based on configuration
|
||||
this.initializeProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize ASR provider based on configuration
|
||||
*/
|
||||
initializeProvider() {
|
||||
try {
|
||||
const providerName = config.ASR_PROVIDER || 'openai';
|
||||
this.asrProvider = ASRProviderFactory.createProvider(providerName, config, config);
|
||||
console.log(`ASR Provider initialized: ${providerName}`);
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize ASR provider:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch ASR provider dynamically
|
||||
* @param {string} providerName - Provider name to switch to
|
||||
*/
|
||||
switchProvider(providerName) {
|
||||
try {
|
||||
this.asrProvider = ASRProviderFactory.createProvider(providerName, config, config);
|
||||
console.log(`ASR Provider switched to: ${providerName}`);
|
||||
} catch (error) {
|
||||
console.error('Failed to switch ASR provider:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure temp directory exists
|
||||
*/
|
||||
ensureTempDirectory() {
|
||||
if (!fs.existsSync(this.tempDir)) {
|
||||
fs.mkdirSync(this.tempDir, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transcribe audio using the configured ASR provider
|
||||
* @param {Buffer} audioBuffer - Raw audio data
|
||||
* @param {Object} options - Transcription options
|
||||
* @returns {Promise<Object>} Transcription result
|
||||
*/
|
||||
async transcribeAudio(audioBuffer, options = {}) {
|
||||
if (!this.asrProvider) {
|
||||
throw new Error('ASR provider not initialized');
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await this.asrProvider.transcribe(audioBuffer, this.tempDir, options);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Transcription error:', error);
|
||||
return {
|
||||
success: false,
|
||||
text: '',
|
||||
error: error.message,
|
||||
timestamp: Date.now(),
|
||||
provider: this.asrProvider.config ? 'unknown' : 'uninitialized'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up old temporary files
|
||||
*/
|
||||
cleanupTempFiles() {
|
||||
try {
|
||||
const files = fs.readdirSync(this.tempDir);
|
||||
const now = Date.now();
|
||||
const maxAge = 10 * 60 * 1000; // 10 minutes
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = path.join(this.tempDir, file);
|
||||
const stats = fs.statSync(filePath);
|
||||
|
||||
if (now - stats.mtime.getTime() > maxAge) {
|
||||
try {
|
||||
fs.unlinkSync(filePath);
|
||||
console.log('Cleaned up old temp file:', file);
|
||||
} catch (error) {
|
||||
console.warn('Failed to cleanup old temp file:', file, error.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('Failed to cleanup temp directory:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if audio buffer has sufficient content for transcription
|
||||
* @param {Buffer} audioBuffer - Audio buffer to check
|
||||
* @returns {boolean} True if buffer has sufficient content
|
||||
*/
|
||||
hasSufficientAudio(audioBuffer) {
|
||||
if (!audioBuffer || audioBuffer.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check minimum duration (at least 0.1 seconds of audio)
|
||||
const minSamples = config.AUDIO_SAMPLE_RATE * 0.1; // 0.1 seconds
|
||||
const minBytes = minSamples * 2; // 16-bit = 2 bytes per sample
|
||||
|
||||
if (audioBuffer.length < minBytes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since we're using Silero VAD for speech detection, we trust its decision
|
||||
// and only check for minimum duration. The energy check is redundant and
|
||||
// can reject valid speech that Silero VAD correctly identified.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current provider information
|
||||
* @returns {Object} Current provider information
|
||||
*/
|
||||
getProviderInfo() {
|
||||
if (!this.asrProvider) {
|
||||
return { provider: 'none', status: 'not initialized' };
|
||||
}
|
||||
|
||||
return {
|
||||
provider: this.asrProvider.constructor.name,
|
||||
model: this.asrProvider.config.model,
|
||||
apiUrl: this.asrProvider.config.apiUrl,
|
||||
status: 'ready'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SpeechToTextService;
|
||||
Reference in New Issue
Block a user