UNPKG

mstf-kit

Version:

一个现代化的 JavaScript/TypeScript 工具库,提供了丰富的常用工具函数

540 lines (417 loc) 13.8 kB
# 非流式音频处理工具使用指南 ## 概述 `audioNonStream` 模块提供了一套完整的工具函数,用于处理非流式接口返回的音频数据。支持多种数据格式(Base64、Blob、ArrayBuffer、File)和灵活的字段路径提取。 ## 主要特性 - ✅ 支持多种数据格式:Base64、Blob、ArrayBuffer、File - ✅ 灵活的字段路径提取:支持嵌套路径(如 `data.audio` 或 `result.voice.content`) - ✅ 自动类型检测:无需手动指定数据类型 - ✅ 自动播放功能:可选的音频自动播放 - ✅ 批量处理:支持批量处理多个音频响应 - ✅ 完整的回调系统:onAudioData、onError、onComplete - ✅ TypeScript 支持:完整的类型定义 - ✅ 调试模式:可选的详细日志输出 ## 安装 ```bash npm install mstf-kit ``` ## 基本使用 ### 1. 处理嵌套字段的 Base64 数据 ```typescript import { processNonStreamAudio } from 'mstf-kit'; // 服务器返回格式: // { // "msg": "success", // "code": 200, // "data": { // "audio": "UklGRiQAAABXQVZFZm10..." // Base64音频数据 // } // } const response = await fetch('/api/audio'); const data = await response.json(); const result = await processNonStreamAudio(data, { audioField: 'data.audio', // 指定音频数据的路径 dataType: 'base64', // 指定数据类型 mimeType: 'audio/wav', // 指定MIME类型 autoPlay: true // 自动播放 }); console.log('音频URL:', result.url); console.log('音频大小:', result.size); console.log('音频类型:', result.mimeType); // 使用音频URL const audioElement = document.querySelector('audio'); audioElement.src = result.url; ``` ### 2. 处理直接字段的 Base64 数据 ```typescript // 服务器返回格式: // { // "msg": "success", // "audio": "UklGRiQAAABXQVZFZm10..." // Base64音频数据 // } const result = await processNonStreamAudio(response, { audioField: 'audio', // 直接指定字段名 autoPlay: true }); ``` ### 3. 自动检测数据类型 ```typescript // 不指定 dataType,工具会自动检测 const result = await processNonStreamAudio(response, { audioField: 'data.audio' // dataType 会自动检测为 'base64' }); ``` ### 4. 处理 ArrayBuffer 响应 ```typescript import axios from 'axios'; // 使用 axios 获取 ArrayBuffer const response = await axios.get('/api/audio', { responseType: 'arraybuffer' }); const result = await processNonStreamAudio(response.data, { dataType: 'arraybuffer', mimeType: 'audio/mp3' }); ``` ### 5. 处理 Blob 响应 ```typescript // 使用 fetch 获取 Blob const response = await fetch('/api/audio'); const blob = await response.blob(); const result = await processNonStreamAudio(blob, { dataType: 'blob' }); ``` ### 6. 处理 File 对象 ```typescript // 从文件上传获取 File 对象 const fileInput = document.querySelector('input[type="file"]'); const file = fileInput.files[0]; const result = await processNonStreamAudio(file, { dataType: 'file', mimeType: 'audio/mp3' }); ``` ## 高级用法 ### 使用回调函数 ```typescript const result = await processNonStreamAudio(response, { audioField: 'data.audio', dataType: 'base64', // 音频数据回调 onAudioData: (blob) => { console.log('收到音频数据:', blob.size, '字节'); // 可以在这里更新UI,显示音频信息 }, // 错误回调 onError: (error) => { console.error('处理音频失败:', error); // 显示错误提示 alert('音频加载失败,请重试'); }, // 完成回调 onComplete: (blob) => { console.log('处理完成'); if (blob) { console.log('成功获取音频,大小:', blob.size); } } }); ``` ### 启用调试模式 ```typescript const result = await processNonStreamAudio(response, { audioField: 'data.audio', debug: true // 启用详细日志输出 }); // 控制台会输出详细的处理过程: // [NonStreamAudio] 开始处理非流式音频响应 {...} // [NonStreamAudio] 按字段路径提取音频数据: data.audio // [NonStreamAudio] 从response.data中提取数据 // [NonStreamAudio] 提取的音频数据类型: string // [NonStreamAudio] 自动检测的数据类型: base64 // [NonStreamAudio] 将Base64数据转换为Blob // [NonStreamAudio] 成功创建Blob: { size: 12345, type: 'audio/mpeg' } // ... ``` ### 批量处理多个音频 ```typescript import { processBatchNonStreamAudio } from 'mstf-kit'; const responses = [ { data: { audio: "base64data1..." } }, { data: { audio: "base64data2..." } }, { data: { audio: "base64data3..." } } ]; const results = await processBatchNonStreamAudio(responses, { audioField: 'data.audio', dataType: 'base64', mimeType: 'audio/wav' }); // 遍历结果 results.forEach((result, index) => { console.log(`音频${index + 1}:`, { url: result.url, size: result.size, type: result.mimeType }); // 创建播放列表 const audioElement = document.createElement('audio'); audioElement.src = result.url; audioElement.controls = true; document.body.appendChild(audioElement); }); ``` ## 便捷函数 ### 快速获取 Blob ```typescript import { getAudioBlob } from 'mstf-kit'; // 快速提取音频 Blob,无需其他信息 const blob = await getAudioBlob(response, 'data.audio', 'base64'); // 使用 Blob const url = URL.createObjectURL(blob); audioElement.src = url; ``` ### 快速创建音频 URL ```typescript import { createAudioUrl } from 'mstf-kit'; // 直接获取可用的音频 URL const url = await createAudioUrl(response, { audioField: 'data.audio', dataType: 'base64' }); audioElement.src = url; ``` ### 下载音频文件 ```typescript import { downloadAudio } from 'mstf-kit'; // 触发浏览器下载音频文件 await downloadAudio(response, 'my-audio.mp3', { audioField: 'data.audio', dataType: 'base64' }); ``` ## 实际应用场景 ### 场景1:TTS(文本转语音)服务 ```typescript import { processNonStreamAudio } from 'mstf-kit'; async function textToSpeech(text: string) { try { // 调用TTS API const response = await fetch('/api/tts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text }) }); const data = await response.json(); // 处理返回的音频数据 const result = await processNonStreamAudio(data, { audioField: 'data.audio', dataType: 'base64', mimeType: 'audio/mp3', autoPlay: true, onAudioData: (blob) => { console.log('TTS音频生成成功,大小:', blob.size); }, onError: (error) => { console.error('TTS失败:', error); alert('语音合成失败,请重试'); } }); return result; } catch (error) { console.error('TTS请求失败:', error); throw error; } } // 使用 const button = document.querySelector('#speak-button'); button.addEventListener('click', async () => { const text = document.querySelector('#text-input').value; await textToSpeech(text); }); ``` ### 场景2:音频文件上传预览 ```typescript import { processNonStreamAudio } from 'mstf-kit'; const fileInput = document.querySelector('#audio-upload'); const audioPreview = document.querySelector('#audio-preview'); fileInput.addEventListener('change', async (event) => { const file = event.target.files[0]; if (!file) return; // 验证文件类型 if (!file.type.startsWith('audio/')) { alert('请选择音频文件'); return; } try { // 处理音频文件 const result = await processNonStreamAudio(file, { dataType: 'file', onAudioData: (blob) => { console.log('音频文件信息:', { name: file.name, size: blob.size, type: blob.type }); } }); // 显示预览 audioPreview.src = result.url; audioPreview.style.display = 'block'; } catch (error) { console.error('处理音频文件失败:', error); alert('无法加载音频文件'); } }); ``` ### 场景3:多语言音频切换 ```typescript import { processBatchNonStreamAudio } from 'mstf-kit'; async function loadMultiLanguageAudio() { // 获取多语言音频数据 const response = await fetch('/api/audio/multi-language'); const data = await response.json(); // 批量处理 const results = await processBatchNonStreamAudio(data.languages, { audioField: 'audio', dataType: 'base64', mimeType: 'audio/mp3' }); // 创建语言选择器 const languageSelector = document.querySelector('#language-selector'); const audioPlayer = document.querySelector('#audio-player'); results.forEach((result, index) => { const language = data.languages[index]; // 添加选项 const option = document.createElement('option'); option.value = result.url; option.textContent = language.name; languageSelector.appendChild(option); }); // 切换语言 languageSelector.addEventListener('change', (event) => { audioPlayer.src = event.target.value; audioPlayer.play(); }); } loadMultiLanguageAudio(); ``` ### 场景4:音频消息系统 ```typescript import { processNonStreamAudio } from 'mstf-kit'; class AudioMessageSystem { private audioCache = new Map<string, string>(); async loadAudioMessage(messageId: string) { // 检查缓存 if (this.audioCache.has(messageId)) { return this.audioCache.get(messageId); } // 获取音频消息 const response = await fetch(`/api/messages/${messageId}/audio`); const data = await response.json(); // 处理音频 const result = await processNonStreamAudio(data, { audioField: 'data.audio', dataType: 'base64', mimeType: 'audio/mp3', onError: (error) => { console.error(`加载音频消息 ${messageId} 失败:`, error); } }); // 缓存URL this.audioCache.set(messageId, result.url); return result.url; } async playAudioMessage(messageId: string) { const url = await this.loadAudioMessage(messageId); const audio = new Audio(url); audio.play(); return audio; } clearCache() { // 释放所有URL this.audioCache.forEach(url => { URL.revokeObjectURL(url); }); this.audioCache.clear(); } } // 使用 const audioSystem = new AudioMessageSystem(); document.querySelectorAll('.audio-message').forEach(element => { element.addEventListener('click', async () => { const messageId = element.dataset.messageId; await audioSystem.playAudioMessage(messageId); }); }); ``` ## API 参考 ### processNonStreamAudio 处理非流式音频响应的主函数。 ```typescript function processNonStreamAudio( response: any, options?: NonStreamAudioOptions ): Promise<NonStreamAudioResult> ``` **参数:** - `response`: 响应数据,可以是完整的响应对象、纯数据对象或直接的音频数据 - `options`: 处理选项 **返回:** Promise<NonStreamAudioResult>,包含: - `blob`: 音频Blob对象 - `url`: 音频URL(可用于audio标签的src) - `size`: 音频大小(字节) - `mimeType`: 音频MIME类型 - `audio`: 音频元素(如果启用了自动播放) ### NonStreamAudioOptions ```typescript interface NonStreamAudioOptions { audioField?: string; // 音频数据字段路径 dataType?: AudioDataType; // 数据类型 mimeType?: string; // MIME类型 autoPlay?: boolean; // 是否自动播放 debug?: boolean; // 是否启用调试日志 onAudioData?: (blob: Blob) => void; // 音频数据回调 onError?: (error: Error) => void; // 错误回调 onComplete?: (blob?: Blob) => void; // 完成回调 } ``` ### AudioDataType ```typescript type AudioDataType = 'base64' | 'blob' | 'arraybuffer' | 'file'; ``` ## 注意事项 1. **内存管理**:使用 `URL.createObjectURL()` 创建的 URL 需要手动释放。如果不再使用音频,请调用 `URL.revokeObjectURL(url)` 释放内存。 2. **自动播放限制**:现代浏览器对自动播放有限制,可能需要用户交互才能播放音频。 3. **CORS 问题**:如果音频来自不同域,确保服务器设置了正确的 CORS 头。 4. **数据大小**:Base64 编码会增加约 33% 的数据大小,对于大文件建议使用 Blob 或 ArrayBuffer。 5. **浏览器兼容性**:确保目标浏览器支持 Web Audio API 和 Blob API。 ## 错误处理 ```typescript try { const result = await processNonStreamAudio(response, { audioField: 'data.audio', dataType: 'base64' }); // 成功处理 console.log('音频URL:', result.url); } catch (error) { // 处理错误 if (error.message.includes('无法从路径')) { console.error('字段路径错误,请检查 audioField 配置'); } else if (error.message.includes('无法检测音频数据类型')) { console.error('数据类型检测失败,请手动指定 dataType'); } else { console.error('未知错误:', error); } } ``` ## 性能优化建议 1. **缓存音频 URL**:对于重复使用的音频,缓存 URL 避免重复处理 2. **批量处理**:使用 `processBatchNonStreamAudio` 批量处理多个音频 3. **懒加载**:只在需要时才加载和处理音频数据 4. **预加载**:对于即将使用的音频,可以提前加载 5. **释放资源**:及时释放不再使用的 URL 和 Blob ## 总结 `audioNonStream` 模块提供了一套完整、灵活、易用的非流式音频处理解决方案。无论是简单的 Base64 数据还是复杂的嵌套响应格式,都能轻松处理。配合完整的 TypeScript 类型支持和丰富的回调系统,可以满足各种音频处理需求。