当前位置: 首页 > news >正文

live2d + edge-tts 优雅的实现数字人讲话 ~

震惊!live2d数字人竟开口说话 ~

之前有想做数字人相关项目,查了一些方案。看了一些三方大厂的商用方案,口型有点尴尬,而且很多是采用视频流的方案,对流量的消耗很大。后来了解了live2d 技术,常在博客网页上见到的看板娘就是live2d技术实现的 ~

说下demo的技术实现,核心采用 live2d 的模型[含有开口说话的动作]  + 文本转语音接口 

1、文本转语音接口

这个接口采用前面分享过的edge-tts项目

基于微软TTS,优雅的实现文本转语音-CSDN博客

代码仓库地址

 GitHub edge-ttsicon-default.png?t=N7T8https://github.com/lyz1810/edge-tts

2、前端实现数字人开口说话

2.1 引入 Live2D 必要的 JavaScript 库
    <script src="./js/live2dcubismcore.min.js"></script><script src="./js/live2d.min.js"></script><script src="./js/pixi.min.js"></script><!-- if only Cubism 4 support--><script src="./js/cubism4.min.js"></script><script src="./js/jquery-3.1.1.min.js"></script><script src="https://unpkg.com/axios/dist/axios.min.js"></script>
2.2 创建页面画布和按钮
<canvas id=canvas></canvas>
<div id="control"><div class="label">1、测试说话</div><button id="play">测试音频</button><br/><br/><div class="label">2、调用接口生成音频</div><textarea id="text" style="width:400px;height:300px;">你好,欢迎光临</textarea><br/><br/><button id="start">开始说话</button>
</div><style>#control {position: absolute;top: 50px;left: 50px;color: #ffffff;font-size: 18px;}.label {font-size: 32px;font-weight: 800;}
</style>
2.3 创建了一个 PIXI 渲染器实例,用于渲染 Live2D 模型
    // 数字人模型const cubism4Model = "./assets/kei_vowels_pro/kei_vowels_pro.model3.json";const live2d = PIXI.live2d;(async function main() {const app = new PIXI.Application({view: document.getElementById("canvas"),autoStart: true,resizeTo: window,backgroundColor: 0x333333});const models = await Promise.all([live2d.Live2DModel.from(cubism4Model)]);models.forEach((model) => {app.stage.addChild(model);const scaleX = (innerWidth) / model.width;const scaleY = (innerHeight) / model.height;// fit the windowmodel.scale.set(Math.min(scaleX, scaleY));model.y = innerHeight * 0.1;draggable(model);});const model4 = models[0];console.log(innerWidth)// model4.x = innerWidth / 2;// 居中显示model4.x = (innerWidth - model4.width) / 2;model4.on("hit", (hitAreas) => {if (hitAreas.includes("Body")) {model4.motion("Tap");}if (hitAreas.includes("Head")) {model4.expression();}});})();
2.4 创建播放音频函数,播放音频 并调用模型开口说话动作
function talk(model, audio) {var audio_link = audio;  //[Optional arg, can be null or empty] [relative or full url path] [mp3 or wav file] "./Keira.wav"var volume = 1; // [Optional arg, can be null or empty] [0.0 - 1.0]var expression = 8; // [Optional arg, can be null or empty] [index|name of expression]var resetExpression = true; // [Optional arg, can be null or empty] [true|false] [default: true] [if true, expression will be reset to default after animation is over]var crossOrigin = "anonymous"; // [Optional arg, to use not same-origin audios] [DEFAULT: null]model.speak(audio_link, {volume: volume,expression: expression,resetExpression: resetExpression,crossOrigin: crossOrigin})model.speak(audio_link)model.speak(audio_link, {volume: volume})model.speak(audio_link, {expression: expression, resetExpression: resetExpression})}
2.5 测试音频播放,并开口说话。点击 测试音频 按钮,测试正常播放调用。一切正常
        $("#play").click(function () {talk(model4, "./demo.mp3");});
2.6 核心来了,让模型根据文字内容开口说话
$("#start").click(function () {console.log($("#text").val());let text = $("#text").val().trim();if (text == "") {alert("请输入内容");return false;}$("#start").prop("disabled", true);axios.get("http://127.0.0.1:2020/dealAudio?file_name=test.mp3&voice=xiaoxiao&text=" + text).then(response => {console.log(response.data);const audioUrl = response.data + "?v=" + new Date().getTime();talk(model4, audioUrl);$("#start").prop("disabled", false);}).catch(error => {console.error('请求接口失败:', error);$("#start").prop("disabled", false);});});

这里调用的接口地址,采用的是文章开头提到的   文本转语音助手

输入文字,点击开始说话 

模型正常说话 ~

live2d的卡通数字人,感觉比3D建模的“真人数字人”效果要好很多,都是张口说话,live2d显的不会那么尴尬 。

live2d的制作成本相对低很多,想商用的话感兴趣可以去查下模型制作教程  ~ 

代码也已开源,仓库地址

live2dSpeekicon-default.png?t=N7T8https://github.com/lyz1810/live2dSpeek

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【在线+sdwebui】在线免费运行stable-diffusion-webui (无需配置环境)
  • 组件间通信高级
  • Windows平台RTSP|RTMP播放器如何实时调节音量
  • 使用 Fyne 构建 GUI 应用:设置标签文本和自增计数器
  • LLMs之Framework:Hugging Face Accelerate后端框架之FSDP和DeepSpeed的对比与分析
  • 【C++第十三章】Stack、Queue和Priority_Queue
  • Scikit-learn:用于数据挖掘和数据分析的简单而有效的工具,建立在 NumPy, SciPy 和 Matplotlib 上。
  • 【数学分析笔记】第2章第2节数列极限(2)
  • 《深入浅出算法竞赛》-递推与递归(笔记版)
  • Python之函数的使用
  • ChatGLM-6B 主要代码分析 RotaryEmbedding
  • vulnhub靶机 DC-9(渗透测试详解)
  • 顺丰科技25届秋季校园招聘常见问题答疑及校招网申测评笔试题型分析SHL题库Verify测评
  • IO器件性能评估
  • 刷刷前端手写题
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • C++11: atomic 头文件
  • CSS实用技巧干货
  • java中的hashCode
  • js递归,无限分级树形折叠菜单
  • Koa2 之文件上传下载
  • Lsb图片隐写
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • MQ框架的比较
  • React中的“虫洞”——Context
  • vue-router的history模式发布配置
  • 从PHP迁移至Golang - 基础篇
  • 多线程 start 和 run 方法到底有什么区别?
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 使用API自动生成工具优化前端工作流
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​低代码平台的核心价值与优势
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (+4)2.2UML建模图
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (自适应手机端)行业协会机构网站模板
  • **CI中自动类加载的用法总结
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET 8.0 中有哪些新的变化?
  • .NET C# 使用GDAL读取FileGDB要素类
  • .NET Remoting学习笔记(三)信道
  • .net SqlSugarHelper
  • .net Stream篇(六)
  • .net 受管制代码
  • .net6+aspose.words导出word并转pdf
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?
  • @RestControllerAdvice异常统一处理类失效原因
  • @Transactional类内部访问失效原因详解
  • @vueup/vue-quill使用quill-better-table报moduleClass is not a constructor
  • [20190401]关于semtimedop函数调用.txt
  • [2019红帽杯]Snake
  • [ajaxupload] - 上传文件同时附件参数值
  • [Android Studio] 开发Java 程序