uniapp 文本转语音

news2024/12/28 22:30:38

在这里插入图片描述

uniapp 文本转语音

  • 基于 Minimax API 的 UniApp 文本转语音工具,支持文本分段、队列播放、暂停恢复等功能。
  • 目前只内置了 Minimax文本转语音
  • Minimax 的语音生成技术以其自然、情感丰富和实时性强而著称
API_KEY、GroupId 获取方法

https://platform.minimaxi.com/user-center/basic-information/interface-key

NPM 地址

特性

  • 🎯 自动文本分段处理
  • 🔄 队列播放管理
  • ⏯️ 支持暂停/恢复
  • 📦 轻量级封装
  • 🎨 完整的事件系统
  • 💫 支持长文本处理

安装 (推荐 npm 安装,而不是导入)

npm install uniapp-text-to-speech

基础使用

import SpeechSynthesisUtil from 'uniapp-text-to-speech';
// 初始化
const tts = new SpeechSynthesisUtil({
	API_KEY: 'your_minimax_api_key', // Minimax API密钥
	GroupId: 'your_group_id', // Minimax 组ID
	MAX_QUEUE_LENGTH: 3// 可选:音频队列最大长度
	modelConfig: { // 可选:音频生成配置
		model: 'speech-01-240228',
		voice_setting: {
			"voice_id": "female-tianmei",
			"speed": 1,
			"vol": 1,
			}
		},
		// 其他配置...
	}
});

// 基础播放
try {
	await tts.textToSpeech('你好,世界!');
} catch (error) {
	console.error('语音合成失败:', error);
}

分段使用

  • 模拟 AI 大模型流式返回数据,自动会处理合成分段:[“你好”,“我是一个ai机器人”,“我的名字叫做阿强”]
import SpeechSynthesisUtil from "uniapp-text-to-speech";
// 初始化
const tts = new SpeechSynthesisUtil({
  API_KEY: "your_minimax_api_key", // Minimax API密钥
  GroupId: "your_group_id", // Minimax 组ID
});

const mockTexts = ['你好,', '我是', '人工智能助手,', '很高兴认识你!'];

try {
	for (const text of mockTexts) {
		await tts.processText(text);
	}
	await tts.flushRemainingText();
} catch (error) {
	addLog(`分段播放失败: ${error.message}`);
}

高级功能

1. 事件监听

import { EventType } from "uniapp-text-to-speech";
// 监听合成开始
tts.on(EventType.SYNTHESIS_START, ({ text }) => {
  console.log(`开始合成文本: ${text}`);
});

// 监听播放开始
tts.on(EventType.AUDIO_PLAY, ({ currentText }) => {
  console.log(`正在播放: ${currentText}`);
  status.value = "播放中";
});

// 监听播放结束
tts.on(EventType.AUDIO_END, ({ finishedText }) => {
  console.log(`播放完成: ${finishedText}`);
  status.value = "就绪";
  progress.value = 100;
});

// 监听错误
tts.on(EventType.ERROR, ({ error }) => {
  console.log(`错误: ${error.message}`);
  status.value = "错误";
});

// 监听暂停
tts.on(EventType.PAUSE, () => {
  console.log("播放已暂停");
  status.value = "已暂停";
  isPaused.value = true;
});

// 监听恢复
tts.on(EventType.RESUME, () => {
  console.log("播放已恢复");
  status.value = "播放中";
  isPaused.value = false;
});

2. 暂停和恢复

// 暂停播放
tts.pause();
// 恢复播放
tts.resume();
// 切换播放/暂停状态
tts.togglePlay();

3. 长文本分段处理

// 自动按标点符号分段处理长文本
await tts.processText("这是第一句话。这是第二句话!这是第三句话?");
// 强制处理剩余未播放的文本
await tts.flushRemainingText();
// 重置文本处理器
tts.resetTextProcessor();

4. 状态管理

// 获取当前状态
const state = tts.getState();
console.log("是否正在播放:", state.isPlaying);
console.log("是否已暂停:", state.isPaused);
// 重置所有状态
tts.reset();

API 文档

构造函数选项

参数类型必填说明
API_KEYstringMinimax API 密钥
GroupIdstringMinimax 组 ID
MAX_QUEUE_LENGTHnumber音频队列最大长度,默认为 3
modelConfigobject合成语音配置,参考minimaxi

事件类型

事件名说明回调参数
SYNTHESIS_START开始合成{ text: string }
SYNTHESIS_END合成结束{ text: string }
AUDIO_PLAY开始播放单个音频片段{ text: string }
AUDIO_END所有音频播放完成{ text: string }
PAUSE暂停播放-
RESUME恢复播放-
ERROR发生错误{ error: Error }

事件说明

  • AUDIO_PLAY: 每个音频片段开始播放时触发
  • AUDIO_END: 仅在所有音频片段都播放完成后触发一次

使用示例

import SpeechSynthesisUtil, { EventType } from "uniapp-text-to-speech";

const tts = new SpeechSynthesisUtil({
  API_KEY: "your_minimax_api_key",
  GroupId: "your_group_id",
  modelConfig: {
    model: "speech-01-240228",
    voice_setting: {
      voice_id: "female-yujie", // 默认使用悦姐声音
      speed: 1.2,
      vol: 1,
    },
  },
});

// 监听播放完成事件
tts.on(EventType.AUDIO_END, ({ text }) => {
  console.log("所有音频播放完成,最后播放的文本:", text);
});

// 分段播放示例
async function playMultipleTexts() {
  await tts.processText("第一段文本");
  await tts.processText("第二段文本");
  await tts.flushRemainingText(); // 确保所有文本都被处理
}

// 重置播放状态
tts.reset();

注意事项

  1. 需要先在 Minimax 申请 API_KEY 和 GroupId
  2. 文本会自动按标点符号分段处理,支持的标点符号优先级:
    • 高优先级:。!?
    • 中优先级:;:
    • 低优先级:,、
  3. 音频队列最大长度默认为 3,可以通过构造函数参数修改
  4. AUDIO_END 事件只会在所有音频片段播放完成后触发一次
  5. 使用 reset() 方法可以重置所有播放状态和计数器

主要的方

方法名说明参数返回值
textToSpeech文本转语音text: stringPromise
processText处理长文本text: stringPromise
pause暂停播放-void
resume恢复播放-void
togglePlay切换播放状态-void
reset重置所有状态-void
on添加事件监听event: EventType, callback: Functionvoid
off移除事件监听event: EventType, callback: Functionvoid

完整的示例代码

<template>
	<div class="speech-demo">
		<!-- 基础演示区域 -->
		<section class="demo-section">
			<h3>基础演示</h3>
			<textarea v-model="basicText" placeholder="请输入要转换的文本"></textarea>
			<button @click="handleBasicSpeech">开始播放</button>
		</section>

		<!-- 分段演示区域 -->
		<section class="demo-section">
			<h3>分段播放演示</h3>
			<div class="segment-container">
				<div v-for="(text, index) in mockTexts" :key="index" class="segment">
					<span>{{ text }}</span>
				</div>
			</div>
			<button @click="handleSegmentSpeech">分段播放</button>
		</section>

		<!-- 高级功能演示区域 -->
		<section class="demo-section">
			<h3>高级功能演示</h3>
			<div class="controls">
				<button @click="handleTogglePlay">{{ isPaused ? '继续' : '暂停' }}</button>
				<button @click="handleReset">重置</button>
			</div>
			<div class="status">
				<p>当前状态: {{ status }}</p>
				<p>播放进度: {{ progress }}%</p>
			</div>
		</section>

		<!-- 事件日志区域 -->
		<section class="demo-section">
			<h3>事件日志</h3>
			<div class="log-container">
				<div v-for="(log, index) in eventLogs" :key="index" class="log-item">
					{{ log }}
				</div>
			</div>
		</section>
	</div>
</template>

<script setup lang="ts">
	import { ref, onMounted, onBeforeUnmount } from 'vue';
	import SpeechSynthesisUtil, { EventType } from 'uniapp-text-to-speech';

	// 响应式状态
	const basicText = ref('你好,这是一个基础示例。');
	const mockTexts = ref(['你好,', '我是', '人工智能助手,', '很高兴认识你!']);
	const status = ref('就绪');
	const progress = ref(0);
	const isPaused = ref(false);
	const eventLogs = ref<string[]>([]);

	// 初始化语音工具
	const tts = new SpeechSynthesisUtil({
		API_KEY: 'your_minimax_api_key', // Minimax API密钥
		GroupId: 'your_group_id', // Minimax 组ID
		modelConfig: {
			model: 'speech-01-240228',
			voice_setting: {
				voice_id: "female-yujie",
				speed: 1,
				vol: 1
			}
		}
	});

	// 添加日志
	const addLog = (message : string) => {
		eventLogs.value.unshift(`${new Date().toLocaleTimeString()}: ${message}`);
		if (eventLogs.value.length > 10) {
			eventLogs.value.pop();
		}
	};

	// 设置事件监听
	const setupEventListeners = () => {
		// 监听合成开始
		tts.on(EventType.SYNTHESIS_START, ({ text }) => {
			addLog(`开始合成文本: ${text}`);
		});

		// 监听播放开始
		tts.on(EventType.AUDIO_PLAY, ({ currentText }) => {
			addLog(`正在播放: ${currentText}`);
			status.value = '播放中';
		});

		// 监听播放结束
		tts.on(EventType.AUDIO_END, ({ finishedText }) => {
			addLog(`播放完成: ${finishedText}`);
			status.value = '就绪';
			progress.value = 100;
		});

		// 监听错误
		tts.on(EventType.ERROR, ({ error }) => {
			addLog(`错误: ${error.message}`);
			status.value = '错误';
		});

		// 监听暂停
		tts.on(EventType.PAUSE, () => {
			addLog('播放已暂停');
			status.value = '已暂停';
			isPaused.value = true;
		});

		// 监听恢复
		tts.on(EventType.RESUME, () => {
			addLog('播放已恢复');
			status.value = '播放中';
			isPaused.value = false;
		});
	};

	// 基础播放示例
	const handleBasicSpeech = async () => {
		try {
			await tts.textToSpeech(basicText.value);
		} catch (error) {
			addLog(`播放失败: ${error.message}`);
		}
	};

	// 分段播放示例
	const handleSegmentSpeech = async () => {
		try {
			for (const text of mockTexts.value) {
				await tts.processText(text);
			}
			await tts.flushRemainingText();
		} catch (error) {
			addLog(`分段播放失败: ${error.message}`);
		}
	};

	// 切换播放/暂停
	const handleTogglePlay = () => {
		tts.togglePlay();
	};

	// 重置播放
	const handleReset = () => {
		tts.reset();
		status.value = '就绪';
		progress.value = 0;
		isPaused.value = false;
		addLog('已重置所有状态');
	};

	// 生命周期钩子
	onMounted(() => {
		setupEventListeners();
	});

	onBeforeUnmount(() => {
		tts.reset();
	});
</script>

<style scoped>
	.speech-demo {
		padding: 20px;
		max-width: 800px;
		margin: 0 auto;
	}

	.demo-section {
		margin-bottom: 30px;
		padding: 20px;
		border: 1px solid #eee;
		border-radius: 8px;
	}

	h3 {
		margin-top: 0;
		margin-bottom: 15px;
		color: #333;
	}

	textarea {
		width: 100%;
		height: 100px;
		padding: 10px;
		margin-bottom: 10px;
		border: 1px solid #ddd;
		border-radius: 4px;
		resize: vertical;
	}

	button {
		padding: 8px 16px;
		margin-right: 10px;
		border: none;
		border-radius: 4px;
		background-color: #4CAF50;
		color: white;
		cursor: pointer;
	}

	button:disabled {
		background-color: #cccccc;
	}

	.segment-container {
		margin-bottom: 15px;
	}

	.segment {
		display: inline-block;
		padding: 5px 10px;
		margin: 5px;
		background-color: #f5f5f5;
		border-radius: 4px;
	}

	.controls {
		margin-bottom: 15px;
	}

	.status {
		padding: 10px;
		background-color: #f9f9f9;
		border-radius: 4px;
	}

	.log-container {
		height: 200px;
		overflow-y: auto;
		padding: 10px;
		background-color: #f5f5f5;
		border-radius: 4px;
	}

	.log-item {
		padding: 5px;
		border-bottom: 1px solid #eee;
		font-family: monospace;
	}
</style>

许可证

MIT

作者

乔振 qiaozhenleve@gmail.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2267131.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端图像处理(二)

目录 一、上传 1.1、文件夹上传以及进度追踪 1.2、拖拽上传 1.3、图片裁剪上传原理 二、图片布局 2.1、渐进式图片 2.2、图片九宫格 2.3、轮播图(Js) 2.3.1、3D动画轮播图 2.3.2、旋转切换的轮播图 2.4、卡片移入翻转效果 2.5、环绕式照片墙 一、上传 1.1、文件夹…

3.BMS系统原理图解读

一、BMS电池板 (1)电池的连接关系&#xff1a;串联 (2)采样控制点&#xff1a;CELL0 - CELL5 (3)端子P1和P3&#xff1a;BAT和BAT- (4)开关S1&#xff1a;控制充放电回路的机械开关 二、BMS控制板 (1)主控MCU 电源 复位 晶振 (2)LED指示灯&#xff1a;4电量指示 1调试指…

用于汽车碰撞仿真的 Ansys LS-DYNA

使用 Ansys LS-DYNA 进行汽车碰撞仿真汽车碰撞仿真 简介 汽车碰撞仿真是汽车设计和安全工程的一个关键方面。这些仿真使工程师能够预测车辆在碰撞过程中的行为&#xff0c;从而有助于改进安全功能、增强车辆结构并符合监管标准。Ansys LS-DYNA 是一款广泛用于此类仿真的强大工具…

使用Java和不同HTTP客户端库发送各种Content-Type类型请求

1. 引言 在HTTP协议中&#xff0c;Content-Type头用于指示请求或响应中数据的媒体类型。了解和正确设置Content-Type 对于确保客户端和服务器之间正确解析数据至关重要。本文将介绍如何使用Java 和 不同的HTTP客户端发送各种Content-Type 类型的请求。 2. 常见的Content-Type…

YOLO11改进-注意力-引入自调制特征聚合模块SMFA

本篇文章将介绍一个新的改进机制——SMFA&#xff08;自调制特征聚合模块&#xff09;&#xff0c;并阐述如何将其应用于YOLOv11中&#xff0c;显著提升模型性能。随着深度学习在计算机视觉中的不断进展&#xff0c;目标检测任务也在快速发展。YOLO系列模型&#xff08;You Onl…

【单片机通讯协议】—— 常用的UART/I2C/SPI等通讯协议的基本原理与时序分析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、通信基本知识1.1 MCU的参见外设1.2 通信的分类按基本的类型从传输方向上来分 二、UART&#xff08;串口通讯&#xff09;2.1 简介2.2 时序图分析2.3 UART的…

Docker 部署 plumelog 最新版本 实现日志采集

1.配置plumelog.yml version: 3 services:plumelog:#此镜像是基于plumelog-3.5.3版本image: registry.cn-hangzhou.aliyuncs.com/k8s-xiyan/plumelog:3.5.3container_name: plumelogports:- "8891:8891"environment:plumelog.model: redisplumelog.queue.redis.redi…

Empire Lupin One靶机

靶机 ip&#xff1a;192.168.152.157 我们访问页面 第一步信息收集 我们先扫描一下端口 扫描到开启了 22 端口 80 端口 我们使用御剑扫描一下网站的后台 我们挨个访问一下 发现 apache 的帮助页面&#xff0c;暂时记录&#xff0c;看看等会有没有需要 我们查看到 robots.tx…

WPF 绘制过顶点的圆滑曲线(样条,贝塞尔)

项目中要用到样条曲线&#xff0c;必须过顶点&#xff0c;圆滑后还不能太走样&#xff0c;捣鼓一番&#xff0c;发现里面颇有玄机&#xff0c;于是把我多方抄来改造的方法发出来&#xff0c;方便新手&#xff1a; 如上图&#xff0c;看代码吧&#xff1a; -------------------…

绝美的数据处理图-三坐标轴-散点图-堆叠图-数据可视化图

clc clear close all %% 读取数据 load(MyColor.mat) %读取颜色包for iloop 1:25 %提取工作表数据data0(iloop) {readtable(data.xlsx,sheet,iloop)}; end%% 解析数据 countzeros(23,14); for iloop 1:25index(iloop) { cell2mat(table2array(data0{1,iloop}(1,1)))};data(i…

hdfs命令(三)- hdfs 管理命令(三)- hdfs dfsadmin命令

文章目录 前言一、hdfs分布式文件系统管理命令1. 介绍2. 语法及解释3. 命令3.1 生成HDFS集群的状态报告3.1.1 语法及解释3.1.2 示例 3.2 重新加载配置文件并更新NameNode中的节点列表3.3 刷新指定DataNode上的NameNode信息3.3.1 语法 3.4 获取并显示指定DataNode的信息3.4.1 语…

Word论文交叉引用一键上标

Word论文交叉引用一键上标 1.进入Microsoft word使用CtrlH快捷键或单击替换按钮 2.在查找内容中输入[^#] 3.鼠标点击&#xff0c;标签为“替换为&#xff1a;”的文本框&#xff0c;注意光标一定要打在图红色方框圈中的文本框中&#xff01; 4.点击格式选择字体 5.勾选上标…

JAVA:最简单多线程方法调用

以下介绍在JAVA中&#xff0c;最简单调用多线程的方法。 在需要使用多线程方法的类中&#xff0c;新增线程类Thread并实现方法run。 //定义多线程class ThreadLinePoints extends Thread{private String m;public ThreadLinePoints(){}public ThreadLinePoints(String m){this…

Hadoop中MapReduce过程中Shuffle过程实现自定义排序

文章目录 Hadoop中MapReduce过程中Shuffle过程实现自定义排序一、引言二、实现WritableComparable接口1、自定义Key类 三、使用Job.setSortComparatorClass方法2、设置自定义排序器3、自定义排序器类 四、使用示例五、总结 Hadoop中MapReduce过程中Shuffle过程实现自定义排序 一…

科技云报到:人工智能时代“三大件”:生成式AI、数据、云服务

科技云报到原创。 就像自行车、手表和缝纫机是工业时代的“三大件”。生成式AI、数据、云服务正在成为智能时代的“新三大件”。加之全球人工智能新基建加速建设&#xff0c;成为了人类社会数字化迁徙的助推剂&#xff0c;让新三大件之间的耦合越来越紧密。从物理世界到数字世…

Windows 11 中部署 Linux 项目

一、总体思路 在 Windows 11 中部署 Linux 项目&#xff0c;主要是借助 Windows Subsystem for Linux&#xff08;WSL&#xff09;来实现。在WSL中新建基于Linux的项目虚拟环境&#xff0c;以供WIN下已克隆的项目使用。WSL 允许在 Windows 系统上运行原生的 Linux 二进制可执行…

【ETCD】【实操篇(十五)】etcd集群成员管理:如何高效地添加、删除与更新节点

etcd 是一个高可用的分布式键值存储&#xff0c;广泛应用于存储服务发现、配置管理等场景。为了确保集群的稳定性和可扩展性&#xff0c;管理成员节点的添加、删除和更新变得尤为重要。本文将指导您如何在etcd集群中处理成员管理&#xff0c;帮助您高效地维护集群节点。 目录 …

数据结构与算法Python版 平衡二叉查找树AVL

文章目录 一、平衡二叉查找树二、AVL树测试三、AVL树-算法分析 一、平衡二叉查找树 平衡二叉查找树-AVL树的定义 AVL树&#xff1a;在key插入时一直保持平衡的二叉查找树。可以利用AVL树实现抽象数据类型映射Map。与二叉查找树相比&#xff0c;AVL树基本上与二叉查找树的实现…

【Redis】Redis 安装与启动

在实际工作中&#xff0c;大多数企业选择基于 Linux 服务器来部署项目。本文演示如何使用 MobaXterm 远程连接工具&#xff0c;在 CentOS 7 上安装和启动 Redis 服务&#xff08;三种启动方式&#xff0c;包括默认启动、指定配置启动和开机自启&#xff09;。在安装之前&#x…

通过Js动态控制Bootstrap模态框-弹窗效果

目的&#xff1a;实现弹出窗、仅关闭弹窗之后才能操作&#xff08;按ESC可退出&#xff09;。自适应宽度与高度、当文本内容太多时、添加滚动条效果。 效果图 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">…