AGV喊话功能模块开发日记

最后更新于2021年8月10日 16:53:10

2021年5月13日 某时某刻:github找到一个java通过TCP/UDP传输的开源代码,win10下单机测试成功。

2021年5月14日 某时某刻:读一读源码,不长,应该很好读。喊话端可以用java做,但是播放端要和现有项目结合在一起,应该要改写成golang吧?顺便今天打算在Ubuntu16环境下测一下单机。
Absolutely fail:Ubuntu16上安装的jdk版本太低了,我把jar包里带的jdk环境下调来适应Ubuntu的jdk版本。但是jar包运行起来又出现了新问题:VMware下的虚拟机没有声音,调过各种奇技淫巧了还不行。深层次说不是没有声音,是连input和output都没有,我吐了。明天打算试一下Hyper-V虚拟机。

2021年5月15日 10:34:41:今天开始日记时间可以精确到秒了,前面的内容其实都是今天写的。
Another failure: Hyper-V可以调节声音,但是仍然没有声音,有output。我试试能不能拯救。
不管了先跑一下jar包看看能不能跑起来,报什么错。
Ubuntu 18.04 解决no soundcards found情况下没有声音的问题 这个好像目测可能估计是有那么点儿用处?不管了回头看一下。
虽然听不到声音但是确确实实跑起来了没有报错,我感觉接下来的重心可以不放在单机上面了,可以读代码然后真正的知道具体到两台真的电脑上怎么传输,现在不还是单机设备模拟嘛。看看吧,不行把自己的笔记本拿来测试一下。
我还有话说:Hyper-V跑ubuntu16简直就是个笑话,不但卡的不行还总是关不了机,要不是VMware没声音劳资才不用这玩意儿。

2021年5月17日 09:24:26:读一下代码,好像没有ip地址,我用台式机发送,笔记本接收,根本收不到。估计是哪里写的localhost。
Java UDP通信:Java DatagramSocket类和DatagramPacket类 找到一个这个,嘿嘿,看一下。
Socket和DatagramSocket的区别
newInstance()&GetInstance()&new:使用Class对象的newInstance()方法创建该Class对象的实例,此时该Class对象必须要有无参数的构造方法。
单例模式及getInstance()的用法
TargetDataLine、SourceDataLine:TargetDataLine是声音的输入(麦克风),而SourceDataLine是输出(音响,耳机)。
百度百科:套接字(socket):Socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。它是网络环境中进程间通信的API(应用程序编程接口),也是可以被命名和寻址的通信端点,使用中的每一个套接字都有其类型和一个与之相连进程。Socket是由IP地址和端口结合的,提供向应用层进程传送数据包的机制。
套接字Socket=(IP地址:端口号),套接字的表示方法是点分十进制的lP地址后面写上端口号,中间用冒号或逗号隔开。每一个传输层连接唯一地被通信两端的两个端点(即两个套接字)所确定。例如:如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23)

虽然代码还没看完,但我突然想开个小差,先把两台不同电脑上的通讯测试成功了再说,现在我把UdpTransmitter的InetAddress.getByName(“localhost”)改成了笔记本的IP地址,然后就测试成功了。但是现在是同一网关(说人话就是连的都是一个Wifi)下的测试,如果是不同路由下会不会有变化呢?我手机连个热点试一下。
连上热点测了一下,还就那个不行,不同路由怎么通信呢?
上网查了一下这个叫跨网段通讯,猪脑接受不了了,估计工厂里也就只有一个局域网(同一子网),回头研究一下吧。看看公司有没有大佬懂的。
反向vpn,NAT击穿,未来要做。
发送端代码看完了,底层不清楚,表面还是比较清晰的。
接下来要读懂接收端代码,最好能自己改写个Golang版本的出来。
还有一件事,这个发送端的前端代码怎么搞?没整过啊?

2021年5月17日 14:21:38:呃,pipelines是什么。。。
接收端代码也不难就是了,看看能不能添加功能,比如说登入和退出的功能。
看了一下github上别人的代码,感觉自己做的也就是沧海一粟。。课堂作业那种,啥也不是。

2021年5月18日 13:20:49:研究了一上午双向通信,确定了新的需求:前端客户端采集声音信息并发送到后端服务端(AGV)发声。存在问题:前端是否能采集声音?还是需要调用接口?
HTML之web项目的目录结构

HTML5操作麦克风获取音频数据(WAV)的一些基础技能:根据该教程run了一个前端接收麦克风输入并录音,下载文件的demo。现在需要的是使用http或者UDP或者什么别的协议把音频实时实时实时传到后端,最好最好最好是UDP传输的,这样我后端代码就不用改了。
Node.js使用UDP通讯
根据这两者组合能搞出一个不??试试。
学习JavaScript
JavaScript使用socket向后端传递信息。
JS实现麦克风录音并通过WebSocket实时传递到后台:这个也看看。
音视频技术入门——音频处理
2021年5月19日 16:02:30:人傻了,先做后端java
spring boot 使用WebSocket与前端进行byte字节数组交互:谢谢大哥救我小命。
2021年5月19日 19:29:47:跑起来了,明天要在这个基础上把结构搞好,增加新功能,有bug修一修。
2021年5月20日 09:24:33:代码功能实现了,我打算看一天原理。
HTTP协议超级详解(原理一)
初识websocket及java服务端的简单实现(原理二)
SpringBoot集成WebSocket,实现后台向前端推送信息:通过该代码可以实现后端向数个前端推送信息,也就是说一台AGV向数台电脑发信息,但我现在需要的是一台电脑向数台AGV发送信息。有没有自己改一下的说法呢?SpringBoot使用Socket向前端推送消息这是前面那篇文章的原出处,可恶啊。

2021年5月20日 15:48:37:前后端都能发送/接收二进制信息和Text信息,有没有方法可以判断传输的信息类型的呢?譬如说前端发给后端信息,后端能知道这是二进制的还是Text的,根据这个调用不同的方法来做相应输出。
关于文字识别并转换成语音我是这样想的:前端传输text格式文件给后端,拿到之后完全用java编写出文字转换成语音的代码并输出。但是目前我还没有去找类似的代码示例,应该有的吧。
2021年5月20日 17:18:08:连按两下“开始通话”按钮就关不掉了,前端设置一下禁用按钮。前端样式稍微修修。
2021年5月21日 10:21:48:整理下前端样式。
2021年5月21日 10:56:23:考虑一下单前端对多后端的实现。
springboot文字转语音(jacob)先记住依赖名称。
2021年5月21日 11:18:18:单前端对多后端的话,后端好像不用改,反正每次启动的ip是不同的,我只要在前端修改连接机器人的ip即可。
我不希望端口号被修改,端口号应该是统一的比如说8080端口;
维护的应该只有URL,不同URL但是同一通道是正常情况;
Websocket连接按钮应该只有一个,input窗口有两个(URL和通道号,在recorder.js中组装起来);
组装之前在hashset中对URL进行检查,检查失败则报错(div返回在前端页面);
前端的写法我觉得是这样的:在recorder.js中维护一个保存URL的hashset,每次通信就在hashset中添加对应AGV的URL并检查其是否重复,重复的话说明当前AGV已连接。
如果要测试的话需要带笔记本来测,我需要两台ip不同的电脑。
还有个问题:如何限制一台电脑上只能打开一个浏览器窗口(或者两窗口同步)?是用cookies吗?

2021年5月21日 13:57:20:前端先就直接输入ip地址吧,目前只能暂时这样,最后再改。
其实我想做成windows输入ip那样的,一共四个输入框打ip地址,打个点就跳下一个。

找下js的array结构中有没有符合我要求的删除元素的方法。
看些东西:
从零开始:编写一个Web服务器—1.了解Web服务器:看了三十秒的猜想:前端页面通过http或者websocket之类的协议向后端发送数据,后端有web server(web服务器)来存储、处理该请求。
Servlet/Tomcat/ Spring 之间的关系:不是Servlet接受的http请求,是Tomcat容器替他接受的。
彻底明白ip地址,区分localhost、127.0.0.1和0.0.0.0
recorder.js 里面的websocket也应该以Array的形式存储,否则后来者会覆盖前者,并且到时候要以循环的方式逐个传递声音信息。
2021年5月21日 16:50:20:项目好像超出我的范围了一点,我想设计一个显示当前存在的连接的窗口,显示目前存在的连接的ip地址和通道id。点击对应的地址可以取消当前连接我还不会做,但是我可以改成在旁边输入想取消的ip和通道就能取消当前连接,这个从前端好实现一点。但是这个的话需要从当前的ipArray里和websocketArray里面都删除当前的连接信息,防止下次因重名未删除导致的连接失败。
还有个大问题就是如果后端服务器失去连接了(比如我ctrlC了我的jar包),前端怎么确定连接失败了?怎么去更新自己的连接列表?不对,我想多了,失去也是失去一个,我只要在onclose回调函数里面增加对列表进行删除就行了,至于删除的函数就叫deleteTransInfo吧。
连接窗口可以稍微放一放再做。
拿笔记本测试。
关闭单条路线功能怎么做。
2021年5月24日 10:33:14:戴尔的SATA默认是RAID on模式的,不在bios里改,找不到硬盘。
ubuntu对Websocket的接受能力好像不如windows,我把后端服务器跑在Ubuntu上,前端的分包大小需要从4096bytes改成1024才能听到正常声音,不报错。具体原因查一下。
代码中无限初始化新的话筒,循环超出上限,程序报错。最傻瓜式的表现是右上角声音选项的窗口变得很长。
修改过期代码:

  1. [Deprecation] The ScriptProcessorNode is deprecated. Use AudioWorkletNode instead.
  2. navigator.getUserMedia is deprecated. Using navigator.mediaDevices.getUserMedia instead.

在测试中观察到话筒接收声音的范围很大,为了产业化后收音的质量考虑,是否可以使用滤波等方式对喊话的质量进行修改(滤波等)。
jacob的原理是调用COM组件实现文字转语音功能,因此只能在windows环境下使用。。。。。。
2021年5月24日 18:01:41语音识别基础篇(一) - CMU Sphinx简介 好像不能用
mozilla TTS
科大讯飞需要收费,体量太大,拿来做简单的TTS感觉是杀鸡用牛刀了。
微软TTS看能不能用。
2021年5月25日 11:10:08:URL直接输入ip地址和端口号,就能打开相应的连接AGV的网页。通道号自动分配。
工程管理方面。
好像让我想明白了,前端代码也是放在AGV上的,那么具体前端代码就不用改,很简单,直接把输入框删除,连接的就是 “ws://localhost:8080/websocket/” + curChannel。具体连接到这个网页用nginx转发(应该是这样)。表现出来的形式就是在url输入机器人的ip或者还有端口,nginx自动转发到对应机器人的那个前端页面上去。
语音先搁一下,先把nginx和工程管理搞明白。
什么是 http 代理,为什么需要 http 代理
由浅入深写代理(1)-介绍
js 程序执行与顺序实现详解
【一句话攻略】彻底理解JS中的回调(Callback)函数
js byteArray 和string 相互转换 UTF-8
(一)SpringBoot搭建基本后端应用 前后端入门系列
2021年5月26日 09:36:34:学习nginx、前端部署。nginx入门教程
阴暗的想法…
2021年5月26日 15:08:28:今天搞明白了一些问题的基本使用和vue的流程:npm是个啥,webpack是个啥,vue和vue-cli都是个啥。我搞了一个基于@vue/cli的工程应该怎么打包。用vue-cli框架重写html+css+js。
2021年6月3日 15:10:05:我又回来啦!!!!
前端不是重点,我现在尝试使用语音识别。
Programme with Ekho 这是一个叫做Ekho的tts,好像不是开源的,但是提供了接口,尝试能不能使用。
Ekho的github repoEkho官网
Building eSpeak NG 这个是Ekho的依赖之一,需要手动安装。

2021年6月4日 09:40:00
Fatal error: gst/gst.h: No such file or directory (using CMake)

2021年6月7日 11:30:00
java sdk常见问题分析解答
使用IDEA在Maven项目中引入自定义的jar包

2021年6月8日 14:01:09
讯飞tts初步试验成功,是比开源项目来的简单多了。目前的问题是:前端传过来的数据走的都是@onmessage这个接口,我是根据发过来的数据包的长度来判断该做出什么动作的。之前只有文字信息和声音信息,就还可以判断,现在文字信息又分两种,一种是操作提示信息:比如说连接成功、连接失败,开始语音通信这样的信息;另一种是业务需要的传送的信息,比如说“倒车请注意”、“请避让机器人”这种信息。后者是需要转成语音的,因此需要将两种信息分开,这样的话之前拿长度区分的取巧方法就不行了。
这个onmessage注解标注的只是一个接口,我能不能多分几个接口呢?在都用@onmessage注解标注的情况下,前端根据什么调用后端接口?

2021年7月26日 11:26:14
springboot解决第三方依赖jar包的问题

2021年7月26日 16:52:41
刚开始出错原因是:使用了第三方的jar包,它们的scope是system,在打jar包时不会自动被打进去,需要手动指定。

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version> 2.4.5</version>
                <configuration>
                    <executable>true</executable>
                    <includeSystemScope>true</includeSystemScope>
                </configuration>
            </plugin>
        </plugins>

第二个问题是:代码跑起来但是报错load library fail,代码20021.
刚开始真的想不通(猪脑爆炸),后来查了讯飞自己的错误码对应关系表才恍然大悟。
讯飞tts中使用了.so文件,不知道是关于什么的库。在打jar包时如果忘记把这部分打进去的话会报错提示加载库失败。这里需要做自解压处理,在spring代码执行前首先从jar包中自动解压出需要的.so文件,参考:Java可执行jar自解压jar内指定文件到指定目录
这俩问题搞了一天才搞好,真的头大。。。。。(我头很大,你忍一下)

2021年7月26日 17:20:02
有个小问题,但是挺恶心的,随着时间的推移,实时通话的延迟变高了,而且是越来越高那种。我没测试太长时间,只测了两分钟,如果这个功能就是用来唠个十分钟的应该是没问题吧?回头试试。

2021年7月30日 16:46:21
尝试把java后端代码修改为golang描述中,目前还是用java的眼光去看待的这次修改,太jb恶心了woc,主要java有onXXXX这种方法,golang里面用的gorilla/websocket,分析下github的例子,抓住重点。

2021年8月3日 16:58:50
在这里插入图片描述
能读取到信息,但是process接收不到,应该是golang内部channel发送接收有问题,难道是没加缓冲,撑爆了???

2021年8月4日 10:52:41
科普常识:常用音频参数解析
Sample Rate, Bit Depth & Buffer Size Explained

2021年8月4日 15:53:11
写一个简单的post请求,js发送到golang。
golang收到文本信息后,建立起连接到官方服务器的websocket连接,在线转换语音后再传回来。

2021年8月10日 09:37:19
写一个离线版本,最好有离线判断,如果现在有网,就在线翻译,如果没有,就离线。

2021年8月10日 10:47:59
目前在做:添加tts的离线版本。这个离线版本好像是会过期的,具体过期了会发生什么,俺也不知道。
tts播放的来源是从端口拿到的audioBytes信息,audioBytes信息再写成.pcm文件。之所以这样做的原因是因为没有找到把.pcm文件变回bytes数组的方法,并且这样更直接,不用再倒腾一遍了,相当于直接使用中间产物生成了声音。可是这样的话,生成的本地音频文件不就很搞笑了吗?(没吊用)应该对其做一些处理,例如新建一个文件夹,保存前十条传送数据的历史记录,新文件覆盖最旧的文件。这样可以从历史记录中读取声音,可以减少tts的数量。
这样看的话,函数的结构分的还是有点问题,应该先把bytes保存为pcm,然后返回audioBytes,新建一个函数去读进audioBytes,这个时候audioBytes就随便我搓圆搓扁了。(传指针好一点,快,即*audioBytes)
翻了一下最早的日期,前前后后猪脑已经爆炸三个月了,这篇博客广义上说也有上万字了,真快啊。

2021年8月10日 11:28:03
应该新增tts转换按钮,转换成功之后再是单次播放和循环播放。
每次转换成功之后可以返回成功的*.pcm文件名字到前端,前端拉个数组啥的保存起来。之后搞个下拉框,里面包含前十次的历史记录,选择并确定之后就能单次或者循环播放。

2021年8月10日 11:57:43
暂时把tts的播放注释掉了,下午把前端的转换和播放分开。

2021年8月10日 15:23:25
golang中sync.RWMutex和sync.Mutex区别

2021年8月10日 16:33:44
需求越分越细:写一个当次数是-1时,无限循环的,还有,我得找到一种方法,在不想让这伞兵玩意儿继续播放的时候停止。我现在想到的方法是借鉴java,新开一个线程去做停止。
GO语言:sync包——WaitGroup

2021年8月11日 11:32:42
GIN路由的底层原理是什么?是新开了两个不同的子线程吗?为什么我在执行一个路由的同时还可以触发另一个路由,并且由于a路由能改变b路由中的全局变量,这种同时触发也能修改到。

2021年8月11日 15:20:54
目前开始真正的做tts的离线版本代码了,后续想做的还有历史记录功能。

2021年8月12日 10:13:46
What is the fxxking CGO?

2021年8月30日 16:56:46

websocket通话成大问题,明天带笔记本好好调试一下前后端参数。采样率不能变。

猜你喜欢

转载自blog.csdn.net/weixin_44445507/article/details/116836437
今日推荐