微信语音转换文字发送发送语音总提示未识别到文字

微信iOS新版语音输入“变”文字为何姗姗来迟?阅读  近日微信发布iOS V6.5.6版,相较之前V6.5.4并没有太大改变,但是却为我们带来了实用的语音转文字功能,远比解决一些已知问题重要得多!iOS新版微信更新了语音输入功能,只要按住按钮说话,声音就能变成文字,非常方便,解决了早前用户吐槽的不便听语音的困扰。
  快随着小智看看新版语音输入的表现吧。
  点击聊天窗口下的+号,弹窗选择语音输入。
  按住说话,系统自动将语音转为文字;发送上屏后可进行手动编辑修改。
  微信语音功能初衷为增进沟通,像对讲机一样通话。它确实方便了发送者,甚至让熟人之间亲密感提升,然而现实生活中的语音消息经常让听者不便。想必是微信产品听到了很多网友关于微信语音消息的吐槽,所以加入了语音转文字的功能。微信在语音方面的改进让人不得不竖起大拇指。
  近几年,整个语音行业随着“人工智能”的东风快速成长,尤以听写技术发展已广泛在语音输入、语音搜索、语音助手等产品中得到应用日臻成熟。日前社交媒体大众热议微信语音,纷纷提到讯飞语音帮助我们在微信中语音输入。没有对比就没有“伤害”,亲测讯飞输入法的准确率比微信高且操作更方便。
  高识别和精准转写技术并不是一蹴而就的,而是一个长期积累的过程。科大讯飞独家推出两大技术——篇章级处理技术和口语风格处理技术。
  通过声学模型建模技术和语言模型建模技术的创新提高了通用场景的识别率,在此基础上利用篇章级处理技术(包括AM自适应、LM自适应、领域LM、语义LM等),使杂乱无章的数据变得有迹可循。值得一提的是,在提高通用识别率方面,科大讯飞掌握了近一两年才成功应用于语音识别中的最新的双向RNN技术和当下比较火的CTC建模技术,使得识别率比DNN技术和双向RNN技术分别相对提升了25%和10%。针对人人对话场景中出现的口语词、犹豫词、重复等情况,通过口语风格处理技术,让机器自动学习重复、会跳弧,解决口语场景下的识别问题。
  人工智能大潮下,语音技术的下一步必然是继续在更智能的方向朝前迈进。除了微信使用讯飞输入法语音,还有一款语音转文字的拳头产品让人眼前一亮。讯飞听见智能会议系统,首款实现会议、演讲场景下以离线方式将发言语音内容实时转换成对应文字。2017湖畔大学马云校长第一课就使用讯飞听见同步出课程字幕。
  只有落到实处技术的进步才是有价值的,将技术应用于功能和产品,从而服务人们的工作生活。对用户而言,现代人的生活是幸福的,语音转写技术的最新发展成果已遍地开花,方便尽在眼前。您需要通过验证再能继续浏览 3秒后开始验证
丨 粤ICP备号-10 丨 新三板上市公司威锋科技(836555)
增值电信业务经营许可证:
Powered by Discuz!
(C) Joyslink Inc. All rights reserved 保留所有权利专业的QQ下载站 本站非腾讯QQ官方网站
本类阅读排行
12345678910
热点图文新闻
微信语音转换文字在哪里设置 微信语音转文字教程
导读:微信的语音转文字已经上线,当然,很多的小伙伴们会纠结不知道该怎么玩。那么微信语音转换文字在哪里设置?文中小编为大家带来了微信语音转文字教程。
微信的语音转文字已经上线,当然,很多的小伙伴们会纠结不知道该怎么玩。那么微信语音转换文字在哪里设置?文中小编为大家带来了微信语音转文字教程。微信语音转文字教程:1、打开手机微信,选择要一个微信好友,或者一个微信群。2、点击【+】号,选择:【语音输入】;3、按住说话,然后,坐等系统将语音自动转为文字;语音转为文字之后,你还可以进行文字编辑。4、点击发送,就可完成语音转文字的全部操作!
更多内容关注腾牛企业微信专区:
出处: 作者:腾牛小编
阅读本文后您有什么感想? 已有 0 人给出评价!手机三星note2-7100微信为什么不能发送语音了,能发送图片,文字。求大神帮忙啊!
在网上搜了很多答案也都试过了,包括删除tencent文件加下MicroMsg文件,也设置了360隐私监控,也试过卸载之前版本替换最新版本,重新启动,但是还是不行,手
按时间排序
你是不是有安装类似360等软件,然后在隐私行为监控功能中禁止了微信使用话筒录音?只要允许就行。我也曾遇到过上述问题,就是这么解决的
您可以邀请下面用户,快速获得回答
擅长领域:&&&&
在手机数码分类下共有80607个回答
擅长领域:&&&&
在手机数码分类下共有22669个回答
擅长领域:&&
在手机数码分类下共有16818个回答
擅长领域:
在手机数码分类下共有8885个回答
擅长领域:&&&&
在手机数码分类下共有7765个回答
weixin_3r654129
擅长领域:
在手机数码分类下共有7269个回答
加载更多答主
感谢您为社区的和谐贡献力量请选择举报类型
经过核实后将会做出处理感谢您为社区和谐做出贡献
点击可定位违规字符位置
确定要取消此次报名,退出该活动?
请输入私信内容:http://www.iosre.com/t/topic/3199
这周做了一个新功能,就是全自动地把微信的语音文件给提取出来,然后转换成文字,一来是一目了然,二来是方便检索。未曾想到的是,在这个过程中,碰到了几个不大不小的坎,踩到了几个不深不浅的坑,在此逐一记录解决方案,供后来人参考。
想要体验这个功能,请参看
定位微信语音文件
通过中提到的思路,定位微信的语音文件并不是什么难事。它们一般在
/WeChat Path/Documents/Random Serial/Audio/Random Serial/random.aud
发出或收到一条语音消息,都会产生一个.aud文件。因为aud不是常见的后缀,我们不知道该用什么方式来播放这条语音,那么就先看看吧。
分析微信语音文件的格式
百度结果很多:
Screen Shot
at 5.49.02 PM.png
可以看到,大多数的帖子,都提到微信语音是amr格式的。其中说,aud就是少了amr文件头的amr文件,只需要在文件开头加上amr标识就可以了:
但是我发现,添加了amr头部的aud文件,还是不能用OSX自带的preview功能播放:
而正常情况下,preview是可以播放amr文件的。这说明,添加了amr标识的文件,并不能被preview正确识别;而这多半是aud文件的问题——它不是amr文件。
我把刚才的aud文件用MacVim重新打开,发现除去我们自行添加的amr头部之外,aud本身含有一个
字样的标识。虽然我对音频编码和文件格式不甚了解,但既然amr文件的头部标识是以#!开头,那么我推测#!SILK_V3应该也是一个文件头。Google之:
Screen Shot
at 6.12.59 PM.png
这样的话,我们基本可以确定微信的语音文件,就是&变种的&silk文件了,我们需要把它修改为纯正的silk文件。为什么说是变种呢?马上就知道了
生成纯正的silk文件
根据果壳网友的分析:
Screen Shot
at 6.29.07 PM.png
微信在aud文件的最开始添加了1个字节,如果把这个字节删掉,这个文件就是一个纯正的silk格式文件。他编译了一个decoder.exe,可以把silk文件给转换成pcm文件;但是我用的是OSX,无法执行exe文件。好么,继续寻找解决方案,把silk文件转换成pcm。
把silk文件转换成pcm文件
又是一顿Google,找到了,博主的目的跟我类似。按照他的操作,先用HomeBrew安装ffmpeg:
brew install ffmpeg,然后从上下载SILKCodec工程(值得一提的是,这个工程的主人是一个中国开发者,音频处理达人,我也已经跟他取得了联系,请教一些音频技术上的问题),然后在SILK_SDK_SRC_ARM里先make
lib,再make decoder,即可生成OSX上的命令行工具decoder。对纯正的silk文件执行命令:/path/to/decoder
/path/to/silk path/to/pcm,即可生成pcm文件。
还可以用将silk转化成pcm,&亲测可用。
把pcm文件转换成wav文件
根据刚才那篇博文,用博主的就可以把pcm文件转换成wav文件,而他的解决方案正是ffmpeg:
ffmpeg -f s16le -ar 24000 -i /path/to/pcm
-f wav /path/to/wav&
播放此wav文件,听到的就是我在微信里发出的语音消息——
“定期整理用户昵称中含有的手机号、用户名、公司。”&(267.3
用科大讯飞SDK解析wav文件
从下载讯飞的官方iOS
demo(注意勾选“语音听写”),在下载的工程中打开“MSCDemo -& MSCDemo -& business -& isr -& IATViewController.h”,其中的pcmFilePath即是音频文件的路径。
在IATViewController.m中的第42行,将pcmFilePath改为wav文件的地址,然后点击下图的“音频流识别”:
Simulator Screen Shot Mar 26, .24 PM.png
即可快速测试解析功能(注:讯飞iOS SDK仅支持pcm和wav格式的音频文件):
Simulator Screen Shot Mar 26, .29 PM.png
对比上面的wav文件,可以看到解析的偏差很大。因为讯飞的中文语音识别技术已经是全球领先的了,所以不大可能会出现这么大的识别错误。问了下讯飞的技术人员,得知问题可能在这些方面:
Screen Shot
at 7.51.11 PM.png
好了,继续研究,看看怎么处理。
进一步处理pcm
和爱拍的CTO指点:
得知讯飞哥们提到的“单通道,16位,”各指的是channels、bit rate/sample size和sample rate。它们在ffmpeg里对应的设置方式分别是-ac
channels、-b:a bitrate、-ar
rate。我们来试试看:
ffmpeg -f s16le -ar 24000 -i /path/to/pcm
-f wav -ar 16000 -b:a 16 -ac 1 /path/to/wav
识别效果如图:
Pasted image
识别得几乎没有问题了。
因为在上面的识别中,“昵称”被听成了“旅程”,还是有些不爽,于是我又擅自改变ffmpeg的参数,想看看能不能做到100%识别准确。最后发现,按照如下的参数配置,识别率是最高的:
ffmpeg -f s16le -ar 12k -ac 2 -i /path/to/pcm
-f wav -ar 16k -ac 1 /path/to/wav
但是,对于这个事实,我只知其然,不知其所以然,还请懂行的高手赐教
在iOS中全自动完成上述操作
总结上面的操作,大致的顺序是:
获取微信语音aud文件;去掉aud文件的第一个字节,将其转换为silk文件;用silk decoder将silk文件转换为pcm文件;用ffmpeg文件将pcm文件转换为wav文件;用讯飞iOS SDK将wav文件转换为文本。
这5步我已经在OSX上用半自动的方式完成了,那么要在iOS中全自动完成,需要做到的,也是5步,与上面一一对应:
hook微信中接收语音信息的函数(提示:这个函数所在的类,是以Mgr结尾的),从中获取aud文件;用NSMutableData处理aud,生成silk;有网友修改过Makefile文件的silk
decoder for iOS,把Makefile中的iOS SDK路径作适当调整,即可编译出iOS上的decoder;值得一提的是,这里的decoder版本是1.0.8而不是最新版的1.0.9;1.0.9的源代码,用1.0.8的Makefile编译会报错失败,具体原因仍待进一步研究。BigBoss源有现成的ffmpeg二进制文件下载;还值得一提的是,iOS 9上通过system()或者posix_spawn()执行命令行工具会碰到一些坑。要解决它们,用到的关键词主要有:沙盒、ldid、RocketBootstrap。讯飞SDK的集成比较简单,用到的主要是[IFlySpeechRecognizer
writeAudio:]及其回调函数。
至此,iOS全自动化解决方案的骨架已经出来了,剩下的肉,就留给各位看官自己来填吧
延伸阅读:
在里,我曾使用讯飞iOS
SDK完成了将微信语音转化为文字的功能。在,&说,微信本身就提供了长按语音转文字的功能,而我在前期研究微信时并没有发现这个功能。经过一番调研,发现只有当系统语言为中文时,微信才会开放这个功能,而我一直使用的是英文系统,所以没看到过这个功能。今天,我们就以这个功能为突破口,摒弃讯飞SDK,采用微信自带的方案,将语音全自动转换为文字。
开启英文版微信的语音转文字功能
这个过程我就不复述了,核心代码是:
%hook VoiceMessageNodeView
- (BOOL)canShowVoiceTransMenu
return YES;
大家编译一个tweak安装一下,就可以在英文版微信里开启这个功能了
IMG_0078.PNG
定位“Convert to Text”这个UIMenuItem的action
照例,我们先用Cycript,定位这个UIMenuItem。停留在上图的界面中,然后用choose命令做一次小小的hack:
cy# choose(UIMenuItem)
[#&&UIMenuItem: 0x&&,#&&UIMenuItem: 0x&&,#&&UIMenuItem: 0x&&,#&&UIMenuItem: 0x&&,#&&UIMenuItem: 0x157afe90&&]
cy# [#0x title]
@&Favorite&
cy# [#0x title]
@&Turn Off Speaker&
cy# [#0x title]
@&More...&
cy# [#0x title]
@&Convert to Text&
好了,找到了“Convert to Text”这个UIMenuItem,我们看看它的action是什么:
@selector(onVoiceTrans:)
好了,onVoiceTrans:就是我们的答案了。咱们grep一遍WeChat的头文件,看看哪个类实现了这个方法:
FunMaker-MBP:~ snakeninny$ grep -r onVoiceTrans: /Users/snakeninny/Code/RE/WeChat
/Users/snakeninny/Code/RE/WeChat/VoiceMessageNodeView.h:- (void)onVoiceTrans:(id)arg1;
Binary file /Users/snakeninny/Code/RE/WeChat/WeChat_arm64.decrypted matches
Binary file /Users/snakeninny/Code/RE/WeChat/WeChat_armv7.decrypted matches
看起来是VoiceMessageNodeView这个类。从类名上猜测,这个类应该是语音信息view的类,在后面我们会验证这个猜测。
查看[VoiceMessageNodeView onVoiceTrans:]的实现细节
把decrypt之后的WeChat可执行文件拖到Hopper里,待分析完毕之后,看看它的反编译C代码:
Pasted image
可以看到很明显的2条分支,1条简单调用了showVoiceTransView,另1条的操作相对复杂。我们先从简单的入手,看看showVoiceTransView都干了些什么。
查看[VoiceMessageNodeView showVoiceTransView]的实现细节
Pasted image
从不够完整的函数实现截图来看,showVoiceTransView做的基本都只是UI层面的操作;它们具体是什么呢?等会再揭晓,我们先看另1条相对复杂的分支。
查看else分支的实现细节
从截图里诸如getStringForCurLanguage:defaultTo:、initWithTitle:andImageName:andContent:andCancelText:、m_voiceTransIntro、show等关键词可以大概猜测,这段代码也是show了一个view出来,貌似也是UI层面的操作。如果if和else都是纯UI操作,那么语音转换的核心代码在哪里呢?是时候上LLDB,往更深一层次的代码去挖掘了。
用LLDB分析[VoiceMessageNodeView onVoiceTrans:]
用LLDB附加WeChat,然后在[VoiceMessageNodeView
onVoiceTrans:]上下断点并触发:
(lldb) br s -a 0x;0x
Breakpoint 1: where = WeChat`___lldb_unnamed_function88615$$WeChat, address = 0x018a2950
Process 3098 stopped
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2950 &+0&: push
{r4, r5, r6, r7, lr}
0x18a2952 &+2&: add
0x18a2954 &+4&: push.w {r8, r10, r11}
0x18a2958 &+8&: sub
我们用ni单步跟一下这个函数,看看每一个objc_msgSend都是在干嘛:
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2974 &+36&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2978 &+40&: mov
0x18a297a &+42&: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a297e &+46&: mov
(lldb) p (char *)$r1
(char *) $0 = 0x0237235d &getMainSettingExt&
(lldb) po $r0
SettingUtil
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2998 &+72&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a299c &+76&: mov
0x18a299e &+78&: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a29a2 &+82&: mov
(lldb) p (char *)$r1
(char *) $2 = 0x &theadSafeGetObject:&
(lldb) po $r0
&CSettingExt: 0x&
(lldb) po $r2
SETTINGEXT_VOICE_TRANS_TIP_TIMES
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a29b8 &+104&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a29bc &+108&: cmp
0x18a29be &+110&: ble
0x18a29d0 &+128&
0x18a29c0 &+112&: movw
(lldb) p (char *)$r1
(char *) $7 = 0x33c13528 &integerValue&
(lldb) po $r0
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2a04 &+180&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2a08 &+184&: str
0x18a2a0a &+186&: movw
0x18a2a0e &+190&: movt
(lldb) p (char *)$r1
(char *) $9 = 0x33c09603 &alloc&
(lldb) po $r0
MMTipsViewController
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2a26 &+214&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2a2a &+218&: mov
0x18a2a2c &+220&: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2a30 &+224&: mov
(lldb) p (char *)$r1
(char *) $11 = 0x33c0c435 &defaultCenter&
(lldb) po $r0
MMServiceCenter
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2a50 &+256&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2a54 &+260&: mov
0x18a2a56 &+262&: movw
0x18a2a5a &+266&: movt
(lldb) p (char *)$r1
(char *) $13 = 0x33c0951e &class&
(lldb) po $r0
MMLanguageMgr
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2a68 &+280&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2a6c &+284&: mov
0x18a2a6e &+286&: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2a72 &+290&: str
(lldb) p (char *)$r1
(char *) $15 = 0x0236945e &getService:&
(lldb) po $r0
&MMServiceCenter: 0x156dd840&
(lldb) po $r2
MMLanguageMgr
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2a8e &+318&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2a92 &+322&: mov
0x18a2a94 &+324&: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2a98 &+328&: str
(lldb) p (char *)$r1
(char *) $18 = 0x0236a7db &getStringForCurLanguage:defaultTo:&
(lldb) po $r0
&MMLanguageMgr: 0x&
(lldb) po $r2
Voice_Trans_Tips_Title
(lldb) po $r3
Voice_Trans_Tips_Title
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2aa8 &+344&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2aac &+348&: mov
0x18a2aae &+350&: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2ab2 &+354&: mov
(lldb) p (char *)$r1
(char *) $22 = 0x33c0c435 &defaultCenter&
(lldb) po $R0
MMServiceCenter
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2ac2 &+370&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2ac6 &+374&: mov
0x18a2ac8 &+376&: mov
0x18a2aca &+378&: mov
(lldb) p (char *)$r1
(char *) $24 = 0x33c0951e &class&
(lldb) po $R0
MMLanguageMgr
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2ace &+382&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2ad2 &+386&: mov
0x18a2ad4 &+388&: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2ad8 &+392&: movw
(lldb) p (char *)$r1
(char *) $26 = 0x0236945e &getService:&
(lldb) po $r0
&MMServiceCenter: 0x156dd840&
(lldb) po $r2
MMLanguageMgr
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2ae8 &+408&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2aec &+412&: mov
0x18a2aee &+414&: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2af2 &+418&: mov
(lldb) po $r0
&MMLanguageMgr: 0x&
(lldb) p (char *)$r1
(char *) $30 = 0x0236a7db &getStringForCurLanguage:defaultTo:&
(lldb) po $r2
Voice_Trans_Tips_Content
(lldb) po $r3
Voice_Trans_Tips_Content
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2b10 &+448&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2b14 &+452&: ldr.w
r1, [r4, r8]
0x18a2b18 &+456&: str.w
r0, [r4, r8]
0x18a2b1c &+460&: mov
(lldb) p (char *)$r1
(char *) $33 = 0x023b452b &initWithTitle:andImageName:andContent:andCancelText:&
(lldb) po $r0
&MMTipsViewController: 0x&
(lldb) po $r2
Audio to Text
(lldb) po $r3
(lldb) x/10 $sp
0x27d99c88: 0x160ed0a90 0x
0x27d99c98: 0xx156dd840 0xx
0x27d99ca8: 0xx
(lldb) po 0x160e8500
This feature only supported for Mandarin Chinese, and the result is for reference only.
(lldb) po 0x
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2b5a &+522&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2b5e &+526&: movw
0x18a2b62 &+530&: movt
0x18a2b66 &+534&: add
(lldb) p (char *)$r1
(char *) $40 = 0x0236cc3c &setM_delegate:&
(lldb) po $r0
&MMTipsViewController: 0x&
(lldb) po $r2
&VoiceMessageNodeView: 0x; frame = (183 0; 128 59); layer = &CALayer: 0x&&
WeChat`___lldb_unnamed_function88615$$WeChat:
0x18a2b6e &+542&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2b72 &+546&: mov
0x18a2b74 &+548&: add
0x18a2b76 &+550&: pop.w
{r8, r10, r11}
(lldb) p (char *)$r1
(char *) $43 = 0x33c0f712 &show&
(lldb) po $r0
&MMTipsViewController: 0x&
到此告一段落。可以看到,这个分支其实是走了else的这一段,就是偏复杂的操作。值得注意的是0x18a2b10处的objc_msgSend,生成了一个关键句“This
feature only supported for Mandarin Chinese, and the result is for reference only.”,我们c一下即可看到:
Pasted image
好了,出现了一个WeChat自定义的弹框。我们用Cycript看看,点击“OK”后会触发什么样的操作。
找到点击弹框上“OK”按钮触发的操作
一般来说,弹框都不会出现在keyWindow上,需要到其他的window里找寻它的踪迹;因此,我们依次检查各个window:
cy# [[UIApp windows][1] recursiveDescription].toString()
` 0x; baseClass = UIW frame = (0 0; 320 45); hidden = YES; gestureRecognizers = &NSArray: 0x&; layer =
0x1601bc50; frame = (12.5 2.5; 40 40); opaque = NO; userInteractionEnabled = NO; layer = &CALayer: 0x&&
0x; frame = (295 12.5; 20 20); opaque = NO; layer = &CALayer: 0x&&
0x; frame = (0 0; 20 20); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = &CALayer: 0x&&
0x; baseClass = UIL frame = (65 5; 0 0); opaque = NO; layer = &CALayer: 0x&&`
cy# [[UIApp windows][2] recursiveDescription].toString()
& 0x156acc50; frame = (0 0; 320 480); hidden = YES; opaque = NO; gestureRecognizers = &NSArray: 0x16455e60&; layer =
cy# [[UIApp windows][3] recursiveDescription].toString()
& 0x162e66e0; frame = (0 0; 320 480); hidden = YES; gestureRecognizers = &NSArray: 0x&; layer =
0x1604ba00&&&
cy# [[UIApp windows][4] recursiveDescription].toString()
` 0x162cd5d0; baseClass = UIW frame = (0 0; 320 480); gestureRecognizers = &NSArray: 0x&; layer =
0x1645eb70&&
0x; frame = (0 0; 320 480); autoresize = W+H; layer = &CALayer: 0x&&
0x; frame = (0 0; 320 480); opaque = NO; autoresize = W+H; layer = &CALayer: 0x156dd060&&
0x; frame = (20 144; 280 192); layer = &CALayer: 0x156e3fc0&&
0x; frame = (0 0; 280 192); opaque = NO; userInteractionEnabled = NO; layer = &CALayer: 0x156e3f40&&
0x; baseClass = UIL frame = (15 22; 250 22); text = 'Audio to Text'; userInteractionEnabled = NO; layer = &CALayer: 0x156d7050&&
0x; baseClass = UIL frame = (16.5 59; 247 62); text = 'This feature only support...'; userInteractionEnabled = NO; layer = &CALayer: 0x156e3090&&
0x1604ae00; baseClass = UIB frame = (0 142; 280 50); opaque = NO; layer = &CALayer: 0x156e3480&&
0x; frame = (127 14; 26 22); text = 'OK'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = &CALayer: 0x156de430&&
0x16035ce0; frame = (0 0; 280 0.5); autoresize = W; layer = &CALayer: 0x156da050&&`
cy# [#0x1604ae00 allTargets]
[NSSet setWithArray:@[#& 0x&&]]]
cy# [#0x1604ae00 allControlEvents]
cy# [#0x1604ae00 actionsForTarget:#0x forControlEvent:64]
@[&onClickBtn:&]
在第5个window里(注意,[UIApp windows][0]就是keyWindow,因此这里是第5个window),我们找到了OK按钮,且它的响应函数是[MMTipsViewController
onClickBtn:];去看看它的实现细节。
查看[MMTipsViewController
onClickBtn:]的实现细节
(lldb) br s -a 0x01cdx
Breakpoint 2: where = WeChat`___lldb_unnamed_function108280$$WeChat, address = 0x01d3c120
Process 3098 stopped
WeChat`___lldb_unnamed_function108280$$WeChat:
0x1d3c120 &+0&: push
{r4, r5, r6, r7, lr}
0x1d3c122 &+2&: add
0x1d3c124 &+4&: push.w {r8, r10, r11}
0x1d3c128 &+8&: mov
WeChat`___lldb_unnamed_function108280$$WeChat:
0x1d3c140 &+32&: blx
0x20eb570 symbol stub for: objc_msgSend
0x1d3c144 &+36&: tst.w
0x1d3c148 &+40&: bne
0x1d3c15 &+60&
0x1d3c14a &+42&: movw
(lldb) p (char *)$r1
(char *) $45 = 0x023e6510 &bIsForbidCancelBtn&
(lldb) po $r0
&MMTipsViewController: 0x&
WeChat`___lldb_unnamed_function108280$$WeChat:
0x1d3c158 &+56&: blx
0x20eb570 symbol stub for: objc_msgSend
0x1d3c15c &+60&: movw
0x1d3c160 &+64&: movt
0x1d3c164 &+68&: add
(lldb) p (char *)$r1
(char *) $47 = 0x023e643d &hideTips&
(lldb) po $r0
&MMTipsViewController: 0x&
WeChat`___lldb_unnamed_function108280$$WeChat:
0x1d3c1a4 &+132&: blx
0x20eb570 symbol stub for: objc_msgSend
0x1d3c1a8 &+136&: mov
0x1d3c1aa &+138&: mov
0x1d3c1ac &+140&: blx
0x20eb5c0 symbol stub for: objc_release
(lldb) p (char *)$r1
(char *) $49 = 0x33c098a1 &respondsToSelector:&
(lldb) p (char *)$r2
(char *) $51 = 0x023b4abf &onClickTipsBtn:&
WeChat`___lldb_unnamed_function108280$$WeChat:
0x1d3c1c2 &+162&: blx
0x20eb570 symbol stub for: objc_msgSend
0x1d3c1c6 &+166&: mov
0x1d3c1c8 &+168&: blx
0x20eb5c0 symbol stub for: objc_release
0x1d3c1cc &+172&: mov
(lldb) p (char *)$r1
(char *) $52 = 0x023b4abf &onClickTipsBtn:&
(lldb) po $r0
&VoiceMessageNodeView: 0x; frame = (183 0; 128 59); layer = &CALayer: 0x&&
(lldb) po $r2
注意,这里调用了[VoiceMessageNodeView onClickTipsBtn:],我们把动态调试暂停在这里,去看看[VoiceMessageNodeView
onClickTipsBtn:]的实现细节。
查看[VoiceMessageNodeView
onClickTipsBtn:]的实现细节
Pasted image
这段代码很容易还原,它的核心操作是:
[[%c(SettingUtil) getMainSettingExt] theadSafeSetObject:@&1& forKey:@&SETTINGEXT_VOICE_TRANS_TIP_TIMES&];
AccountStorageMgr *manager = [[%c(MMServiceCenter) defaultCenter] getService:[%c(AccountStorageMgr) class]];
[manager SaveSettingExt];
从函数及参数名来看,这段代码的功能貌似就是作为语音转换的开关。我们继续ni,看看还有没有其他玄机。
继续查看[MMTipsViewController
onClickBtn:]的实现细节
WeChat`___lldb_unnamed_function108280$$WeChat:
0x1d3c1e8 &+200&: blx
0x20eb570 symbol stub for: objc_msgSend
0x1d3c1ec &+204&: mov
0x1d3c1ee &+206&: mov
0x1d3c1f0 &+208&: blx
0x20eb5c0 symbol stub for: objc_release
(lldb) p (char *)$r1
(char *) $55 = 0x33c098a1 &respondsToSelector:&
(lldb) p (char *)$r2
(char *) $56 = 0x023b4acf &onClickTipsBtn:Index:&
(lldb) po $r0
&VoiceMessageNodeView: 0x; frame = (183 0; 128 59); layer = &CALayer: 0x&&
因为[VoiceMessageNodeView respondsToSelector:@selector(onClickTipsBtn:Index:)]的返回值为NO,所以这一大段分析,得出的核心代码,就是上面提取出的这段,且它的功能,就是开启微信语音转换功能的开关。这段代码怎么使用呢?我们只需要在微信第一次启动时调用这段代码,就可以开启微信的语音转换功能了。
开启了语音转换之后,我们取得了阶段性胜利。但是下一个问题来了,哪段代码是负责实际转换操作的呢?这才是我们的重中之重。
找到语音转换操作的核心代码
刚才的[VoiceMessageNodeView onClickTipsBtn:]里,除了开启语音转换功能的代码外,还有一个低调的showVoiceTransView,它的调用者是一个VoiceMessageNodeView对象,我猜语音转换操作的核心代码就藏着这里。我们看看它的反编译代码:
Pasted image
还挺复杂。咱们动态跟跟看:
(lldb) br s -a 0x;0x64000
Breakpoint 3: where = WeChat`___lldb_unnamed_function88616$$WeChat, address = 0x018a2b84
Process 3098 stopped
WeChat`___lldb_unnamed_function88616$$WeChat:
0x18a2b84 &+0&: push
{r4, r5, r6, r7, lr}
0x18a2b86 &+2&: add
0x18a2b88 &+4&: str
0x18a2b8c &+8&: vpush
WeChat`___lldb_unnamed_function88616$$WeChat:
0x18a2bde &+90&:
0x20eb570 symbol stub for: objc_msgSend
0x18a2be2 &+94&:
0x18a2be4 &+96&:
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2be8 &+100&: mov
(lldb) p (char *)$r1
(char *) $59 = 0x0236deb3 &getAppViewControllerManager&
Process 3098 stopped
WeChat`___lldb_unnamed_function88616$$WeChat:
0x18a2be2 &+94&:
0x18a2be4 &+96&:
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2be8 &+100&: mov
0x18a2bea &+102&: movw
(lldb) po $r0
&CAppViewControllerManager: 0x1601dcb0&
* thread #1: tid = 0x3a3d5, 0x018a2bf8 WeChat`___lldb_unnamed_function88616$$WeChat + 116, queue = 'com.apple.main-thread', stop reason = instruction step over
frame #0: 0x018a2bf8 WeChat`___lldb_unnamed_function88616$$WeChat + 116
WeChat`___lldb_unnamed_function88616$$WeChat:
0x18a2bf8 &: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2bfc &: mov
0x18a2bfe &: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2c02 &: mov
(lldb) p (char *)$r1
(char *) $61 = 0x023743eb &getMainWindow&
(lldb) po $r0
0x1601dcb0&
Process 3098 stopped
* thread #1: tid = 0x3a3d5, 0x018a2bfc WeChat`___lldb_unnamed_function88616$$WeChat + 120, queue = 'com.apple.main-thread', stop reason = instruction step over
frame #0: 0x018a2bfc WeChat`___lldb_unnamed_function88616$$WeChat + 120
WeChat`___lldb_unnamed_function88616$$WeChat:
0x18a2bfc &: mov
0x18a2bfe &: blx
0x20eb610 symbol stub for: objc_retainAutoreleasedReturnValue
0x18a2c02 &: mov
0x18a2c04 &: cbz
r5, 0x18a2c30 &
(lldb) po $r0
0x156b8ae0; baseClass = UIW frame = (0 0; 320 480); autoresize = W+H; gestureRecognizers = &NSArray: 0x156b9290&; layer =
0x156b8df0&&
WeChat`___lldb_unnamed_function88616$$WeChat:
0x18a2d0e &+394&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2d12 &+398&: movw
0x18a2d16 &+402&: add.w
0x18a2d1a &+406&: movt
(lldb) po $r2
{m_uiMesLocalID=2, m_ui64MesSvrID=4038564, m_nsFromUsr=wxi*f12~19, m_nsToUsr=we*in~6, m_uiStatus=2, type=34, msgSource=&(null)&}
(lldb) po $r0
&VoiceTransFloatPreview: 0x16543cd0; baseClass = UIW frame = (0 0; 320 480); hidden = YES; gestureRecognizers = &NSArray: 0x&; layer = &UIWindowLayer: 0x15624d10&&
(lldb) p (char *)$r1
(char *) $77 = 0x &setVoiceMsg:&
WeChat`___lldb_unnamed_function88616$$WeChat:
0x18a2d40 &+444&: blx
0x20eb570 symbol stub for: objc_msgSend
0x18a2d44 &+448&: add
0x18a2d46 &+450&: vpop
0x18a2d4a &+454&: ldr
(lldb) p (char *)$r1
(char *) $79 = 0x &showWithAnimate:&
我省略了一些明显是UI层的操作,留下了上面这些objc_msgSend。我们回顾一下微信语音转文字时的UI效果:当我们点击“Convert to Text”之后,新的界面上出现“converting...”的字样,等待几秒钟,转换好的文字就会出现在界面上。这说明,微信可能是先把显示文字的UI给画出来,以“converting...”提示用户等待,同时开一个另一个线程去转换语音,待语音转换完毕后再把文字给显示在UI上。结合我们的猜测,上面的一系列objc_msgSend中,最可疑的无疑是[VoiceTransFloatPreview
setVoiceMsg:(CMessageWrap *)]和[VoiceTransFloatPreview
showWithAnimate:]。我们分别看一下它们的实现细节。
查看[VoiceTransFloatPreview
setVoiceMsg:]的实现细节
Pasted image
看起来只是一个普通的setter,没有什么特别的地方,继续下一目标。
查看[VoiceTransFloatPreview
showWithAnimate:]的实现细节
Pasted image
在一系列的函数中,[r4 onStartGet]引起了我的注意,它是除IdleTimerUtil外,唯一没有出现UI字眼的函数;我们看看它的实现。
查看[VoiceTransFloatPreview
onStartGet]的实现细节
看到VoiceTransHelper的字眼,我知道我们的分析快要接近尾声了。打开VoiceTransHelper.h,诸如
- (id)initWithVoiceMsg:(id)arg1 VoiceID:(id)arg2;
- (void)startVoiceT
- (void)stopVoiceT
- (void)HandleGetVoiceTransResp:(id)arg1 Event:(unsigned long)arg2;
等可疑函数尽收眼底,等待检阅。对于这个类的调研,就留作练习,交给正在阅读此帖的你来完成吧~!
微信的语音识别技术想必不会比讯飞强大,仅论语音识别配置的精细度来说,讯飞就要专业很多。但是,如果我们的需求仅仅是简单的语音识别,没有太多定制化的需求,那么打包讯飞SDK之后的dylib会比采用微信原生语音转换的dylib大5M左右。跟我在提到的思路一脉相承——我们的dylib存活在别人的进程里,相当于是我们去其他人家做客,不给别人添麻烦是基本的教养和礼貌,能够节省5+M内存,是一种尊重他人劳动成果的体现,更是我们自我要求精益求精的缩影。工程师的素养体现在一点一滴中,见微知著,才能成就大业;祝愿大家都能持续进步,再攀高峰
微信小程序语音转化为文字
1、微信小程序录音,提交到服务器(此时音频格式为silk);
2、利用silk-v3-decoder(https://github.com/kn007/silk-v3-decoder), 把silk...
科大讯飞语音识别(获取音频流文件中文字)
使用讯飞sdk获取视频文件中的音频文字
音频视频自动提取字幕(extract subtitle from audios and vedios)
自动提取字幕的功能,在国外视频网站Youtube和社交巨头Facebook都已经上线多年,但国内各类视频和音频站都没有类似的功能,所有花了点时间调研了一下subtitle的自动提取功能:1. 开源语音...
音频自动化测试
需求在嵌入式系统中音频的重要性一直被忽视,图像的指标一般都是放在首位的。产生这个问题的一个很大原因就是过去的民用的嵌入式系统不是很多,大部分都是工业用的。现在产生了很多的桌上设备和便携设备的产品,也就...
&em&微信&/em&小程序语音silk转换为mp3示例代码主要运用于&em&微信&/em&小程序录制的语音,其他设备...小程序及&em&语音转文字&/em&
&em&微信&/em&小程序语音使用ffmpeg进行格式转换
&em&微信&/em&小程序语音识别...
融云SDK 使用很方便,简单配置就可以搭建即时通讯功能,配合科大讯飞的语音识别, 即可实现微信中语音消息转换为文字的功能
融云sdk的基本使用就不细说了, 网上很多资料
仿&em&微信&/em&录音 科大讯飞 amr录音文件转文字 立即下载
上传者: thinkleo119 时间:
综合评分: 1 积分/C币:10
mui中的本地&em&语音转文字&/em&,而不用讯飞的...
&em&微信语音&/em&提取器
上传大小:8.86MB &em&微信语音&/em&转换&em&文字&/em& &em&微信语音&/em&提取器,可以利用该软件,将&em&微信语音&/em&提取并转化为&em&文字&/em&,在本地进行永久保存。...
语音听写SDK适配安卓6.0需要手动申请权限
关于语音听写SDK的开发,参考科大讯飞开放平台官网为准在百度搜索讯飞科技开放平台,自己注册账号 自己创建一个新应用在控制台界面创建完应用,然后选择SDK...
没有更多推荐了,

我要回帖

更多关于 微信怎么设置语音转换文字发送 的文章

 

随机推荐