Android 讯飞语音识别功能开发

以下代码主要参考博客:
Android 科大讯飞语音识别

Android蓝牙串口开发部分请参照博客:
Android蓝牙串口开发

讯飞语音官方开发文档:
语音听写 Android SDK 文档

文章目录

  • 前言
  • 一、SDK的下载和导入
    • 1.SDK的下载
    • 2.新建工程
    • 3.配置项目
      • a.导包
      • b.权限
      • c.修改buid.gradle
  • 二、工具类
    • 1.Json解析类
    • 2.语音识别相关方法
      • a.变量声明
      • b.权限请求
      • c.语音监听
      • d.数据解析
      • c.参数配置
  • 三、调用代码编写
    • 1.点击事件的监听
    • 2.识别结果的显示
    • 3.语音命令识别和发送
  • 总结


前言

语音识别目前使用的比较频繁,项目需要使用语音识别用户指令,然后通过蓝牙通信传递指定,命令下位机做出反应。手机端主要负责命令的发送,选用讯飞语音SDK,学习官方文档和参考博客进行开发。写这篇博客记录一下。


一、SDK的下载和导入

这一部分可以可以参照讯飞语音官方文档来进行
官方文档:语音听写 Android SDK 文档

1.SDK的下载

首先在讯飞开放平台登录,没有账号进行注册
在这里插入图片描述
在控制台中,按流程创建新应用。
在这里插入图片描述
在这里插入图片描述
在下方的SDK下载中,下载相应的SDK。
在这里插入图片描述
解压完成后,先建立工程。

2.新建工程

打开Android Studio 开发平台,新建工程画好前端设计界面,建立工程这一部分就不在赘述。
在这里插入图片描述

3.配置项目

a.导包

将解压后的libs文件夹中的文件放入项目的libs文件夹中。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对Msc包右键,选择Add As Library导入,此时Msc包可展开。
然后再添加assets,将assets文件夹添加到工程main文件夹下面。
在这里插入图片描述

b.权限

导包完成后,我们需要给App一些必要权限,来使用手机的硬件功能。

<!--连接网络权限,用于执行云端语音能力 --><uses-permission android:name="android.permission.INTERNET"/><!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 --><uses-permission android:name="android.permission.RECORD_AUDIO"/><!--读取网络信息状态 --><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><!--获取当前wifi状态 --><uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/><!--允许程序改变网络连接状态 --><uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/><!--读取手机信息权限 --><uses-permission android:name="android.permission.READ_PHONE_STATE"/><!--读取联系人权限,上传联系人需要用到此权限 --><uses-permission android:name="android.permission.READ_CONTACTS"/><!--外存储写权限,构建语法需要用到此权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><!--外存储读权限,构建语法需要用到此权限 --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><!--配置权限,用来记录应用配置信息 --><uses-permission android:name="android.permission.WRITE_SETTINGS"tools:ignore="ProtectedPermissions" /><!--手机定位信息,用来为语义等功能提供定位,提供更精准的服务--><!--定位信息是敏感信息,可通过Setting.setLocationEnable(false)关闭定位请求 --><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/><!--如需使用人脸识别,还要添加:摄相头权限,拍照需要用到 --><uses-permission android:name="android.permission.CAMERA" />

c.修改buid.gradle

打开buid.gradle后,在文件中做以下修改。

dependencies {implementation fileTree(include: ['*.jar'], dir: 'libs')implementation 'androidx.appcompat:appcompat:1.0.2'implementation 'androidx.constraintlayout:constraintlayout:1.1.3'testImplementation 'junit:junit:4.12'androidTestImplementation 'androidx.test.ext:junit:1.1.1'androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'implementation files('libs/Msc.jar')
}

然后点击Sync Now。
在这里插入图片描述

二、工具类

1.Json解析类

识别语音时,需要用到Json格式,所以需要有一个解析Json格式的类。
在工程中,新建一个JsonParser 的类。

package com.example.speechrecognitionforbluetooth;import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;/*** Json结果解析类*/
public class JsonParser {public static String parseIatResult(String json) {StringBuffer ret = new StringBuffer();try {JSONTokener tokener = new JSONTokener(json);JSONObject joResult = new JSONObject(tokener);JSONArray words = joResult.getJSONArray("ws");for (int i = 0; i < words.length(); i++) {// 转写结果词,默认使用第一个结果JSONArray items = words.getJSONObject(i).getJSONArray("cw");JSONObject obj = items.getJSONObject(0);ret.append(obj.getString("w"));
//				如果需要多候选结果,解析数组其他字段
//				for(int j = 0; j < items.length(); j++)
//				{
//					JSONObject obj = items.getJSONObject(j);
//					ret.append(obj.getString("w"));
//				}}} catch (Exception e) {e.printStackTrace();} return ret.toString();}public static String parseGrammarResult(String json) {StringBuffer ret = new StringBuffer();try {JSONTokener tokener = new JSONTokener(json);JSONObject joResult = new JSONObject(tokener);JSONArray words = joResult.getJSONArray("ws");for (int i = 0; i < words.length(); i++) {JSONArray items = words.getJSONObject(i).getJSONArray("cw");for(int j = 0; j < items.length(); j++){JSONObject obj = items.getJSONObject(j);if(obj.getString("w").contains("nomatch")){ret.append("没有匹配结果.");return ret.toString();}ret.append("【结果】" + obj.getString("w"));ret.append("【置信度】" + obj.getInt("sc"));ret.append("\n");}}} catch (Exception e) {e.printStackTrace();ret.append("没有匹配结果.");} return ret.toString();}public static String parseLocalGrammarResult(String json) {StringBuffer ret = new StringBuffer();try {JSONTokener tokener = new JSONTokener(json);JSONObject joResult = new JSONObject(tokener);JSONArray words = joResult.getJSONArray("ws");for (int i = 0; i < words.length(); i++) {JSONArray items = words.getJSONObject(i).getJSONArray("cw");for(int j = 0; j < items.length(); j++){JSONObject obj = items.getJSONObject(j);if(obj.getString("w").contains("nomatch")){ret.append("没有匹配结果.");return ret.toString();}ret.append("【结果】" + obj.getString("w"));ret.append("\n");}}ret.append("【置信度】" + joResult.optInt("sc"));} catch (Exception e) {e.printStackTrace();ret.append("没有匹配结果.");} return ret.toString();}public static String parseTransResult(String json, String key) {StringBuffer ret = new StringBuffer();try {JSONTokener tokener = new JSONTokener(json);JSONObject joResult = new JSONObject(tokener);String errorCode = joResult.optString("ret");if(!errorCode.equals("0")) {return joResult.optString("errmsg");}JSONObject transResult = joResult.optJSONObject("trans_result");ret.append(transResult.optString(key));/*JSONArray words = joResult.getJSONArray("results");for (int i = 0; i < words.length(); i++) {JSONObject obj = words.getJSONObject(i);ret.append(obj.getString(key));}*/} catch (Exception e) {e.printStackTrace();}return ret.toString();}
}

用来给语音识别的方法调用。

2.语音识别相关方法

现在需要实现语音识别的核心代码了,具体代码请参考官方文档Demo或访问参考博客学习,这里做一个展示。

a.变量声明

首先对比要的包进行导入。

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import static android.widget.Toast.LENGTH_SHORT;

对于语音识别部分必要的变量进行声明。

//语音识别部分private SpeechRecognizer mIat;// 语音听写对象private RecognizerDialog mIatDialog;// 语音听写UI// 用HashMap存储听写结果private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();private SharedPreferences mSharedPreferences;//缓存private String mEngineType = SpeechConstant.TYPE_CLOUD;// 引擎类型private String language = "zh_cn";//识别语言private TextView tvResult;//识别结果//语音识别功能按钮private Button mBTN_SPEECH;private String resultType = "json";//结果内容数据格式

b.权限请求

调用过程中,需要动态的获取权限。

 /*** android 6.0 以上需要动态申请权限*/private void initPermission() {String permissions[] = {Manifest.permission.RECORD_AUDIO,Manifest.permission.ACCESS_NETWORK_STATE,Manifest.permission.INTERNET,Manifest.permission.WRITE_EXTERNAL_STORAGE};ArrayList<String> toApplyList = new ArrayList<String>();for (String perm : permissions) {if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, perm)) {toApplyList.add(perm);}}String tmpList[] = new String[toApplyList.size()];if (!toApplyList.isEmpty()) {ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);}}/*** 权限申请回调,可以作进一步处理** @param requestCode* @param permissions* @param grantResults*/@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {// 此处为android 6.0以上动态授权的回调,用户自行实现。}

c.语音监听

/*** 初始化监听器。*/private InitListener mInitListener = new InitListener() {@Overridepublic void onInit(int code) {Log.d(TAG, "SpeechRecognizer init() code = " + code);if (code != ErrorCode.SUCCESS) {showMsg("初始化失败,错误码:" + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");}}};/*** 听写UI监听器*/private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {public void onResult(RecognizerResult results, boolean isLast) {printResult(results);//结果数据解析}/*** 识别回调错误.*/public void onError(SpeechError error) {showMsg(error.getPlainDescription(true));}};/*** 提示消息* @param msg*/private void showMsg(String msg) {Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();}@Overrideprotected void onDestroy() {super.onDestroy();if (null != mIat) {// 退出时释放连接mIat.cancel();mIat.destroy();}}

d.数据解析

分析得到的数据,利用Text将结果显示出来,然后分析结果,利用蓝牙将指令发送出去。

/*** 数据解析** @param results*/private void printResult(RecognizerResult results) {String text = JsonParser.parseIatResult(results.getResultString());String sn = null;// 读取json结果中的sn字段try {JSONObject resultJson = new JSONObject(results.getResultString());sn = resultJson.optString("sn");} catch (JSONException e) {e.printStackTrace();}mIatResults.put(sn, text);StringBuffer resultBuffer = new StringBuffer();for (String key : mIatResults.keySet()) {resultBuffer.append(mIatResults.get(key));}mET_DATE.setText(resultBuffer.toString());//听写结果显示sendCMDByBluetooth(resultBuffer.toString());//发送命令}

c.参数配置

/*** 参数设置** @return*/public void setParam() {// 清空参数mIat.setParameter(SpeechConstant.PARAMS, null);// 设置听写引擎mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);// 设置返回结果格式mIat.setParameter(SpeechConstant.RESULT_TYPE, resultType);if (language.equals("zh_cn")) {String lag = mSharedPreferences.getString("iat_language_preference","mandarin");Log.e(TAG, "language:" + language);// 设置语言mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");// 设置语言区域mIat.setParameter(SpeechConstant.ACCENT, lag);} else {mIat.setParameter(SpeechConstant.LANGUAGE, language);}Log.e(TAG, "last language:" + mIat.getParameter(SpeechConstant.LANGUAGE));//此处用于设置dialog中不显示错误码信息//mIat.setParameter("view_tips_plain","false");// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理mIat.setParameter(SpeechConstant.VAD_BOS, mSharedPreferences.getString("iat_vadbos_preference", "4000"));// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音mIat.setParameter(SpeechConstant.VAD_EOS, mSharedPreferences.getString("iat_vadeos_preference", "1000"));// 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点mIat.setParameter(SpeechConstant.ASR_PTT, mSharedPreferences.getString("iat_punc_preference", "1"));// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限mIat.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/iat.wav");}

三、调用代码编写

在准备的工作基本完成之后,现在就需要在主程序的按逻辑去调用方法实现功能。

1.点击事件的监听

首先对于屏幕实现一个点击事件的监听。

public class MainActivity extends AppCompatActivity implements View.OnClickListener{//这里省略了其他必要的代码,仅展示改动部分private static final String TAG ="MainActivity" ;/*** 屏幕点击响应事件* @param v*/@Overridepublic void onClick(View v) {if( null == mIat ){// 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688showMsg( "创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化" );return;}mIatResults.clear();//清除数据setParam(); // 设置参数mIatDialog.setListener(mRecognizerDialogListener);//设置监听mIatDialog.show();// 显示对话框}
}

2.识别结果的显示

结果的显示包含在数据分析的部分代码中

//该部分代码位于数据解析代码段中,具体情况自己按情况更改
mET_DATE.setText(resultBuffer.toString());//听写结果显示
sendCMDByBluetooth(resultBuffer.toString());//发送命令

3.语音命令识别和发送

检测到语音输入后,产生一个识别结果,显示出来后,根据自己需要的判断逻辑对识别结果进行分析,发出指令。

/*** 识别语音由蓝牙发送指令* @param Speech* 为语音指令*/public void sendCMDByBluetooth(String Speech){//去掉命令中的句号String CMD = Speech.substring(0,Speech.indexOf("。"));//判断是否打开蓝牙if (CONNECT_STATUS) {switch (CMD){case "打开灯光":{write("A");Toast.makeText(MainActivity.this, "指令:打开灯光 CMD:A", LENGTH_SHORT).show();break;}case "关闭灯光":{write("B");Toast.makeText(MainActivity.this, "指令:关闭灯光 CMD:B", LENGTH_SHORT).show();break;}case "打开风扇":{write("C");Toast.makeText(MainActivity.this, "指令:打开风扇 CMD:C", LENGTH_SHORT).show();break;}case "关闭风扇":{write("D");Toast.makeText(MainActivity.this, "指令:关闭风扇 CMD:D", LENGTH_SHORT).show();break;}}} else {Toast.makeText(getApplicationContext(), "请先连接蓝牙", Toast.LENGTH_SHORT).show();}}

总结

在这里插入图片描述

对我来说,该项目主要的难点在于对SDK的使用,以及类的调用。更灵活的使用还需要加深理解。

关于Android经典蓝牙串口开发在我的另一篇博客有记录。
Android蓝牙串口开发

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp - 接入科大讯飞语音评测

欢迎关注微信公众号&#xff1a;FSA全栈行动 &#x1f44b; 一、简介 科大讯飞语音评测可以对字、词、句、篇章等题型进行多维度评分&#xff08;准确度、流畅度、完整度、声韵调型等&#xff09;&#xff0c;支持中文和英文。最新的流式版使用 webSocket 调用接口&#xff0c…

目标检测算法——YOLOv5/YOLOv7改进之结合​PP-LCNet(轻量级CPU网络)

>>>深度学习Tricks&#xff0c;第一时间送达<<< 目录 ​PP-LCNet——轻量级且超强悍的CPU级骨干网络&#xff01;&#xff01; &#xff08;一&#xff09;前沿介绍 1.PP-LCNet主要模块 2.相关实验结果 &#xff08;二&#xff09;YOLOv5/YOLOv7改进之结…

从Blip2到Segment Anything视觉语义金字塔+ChatGPT= 把图片变文本段落, 8G显存即可Run...

关注公众号&#xff0c;发现CV技术之美 8G GPU显存即可以运行 Twitter链接&#xff1a;https://twitter.com/awinyimgprocess/status/1646225454599372800?s46&tHvOe9T2n35iFuCHP5aIHpQ 代码链接&#xff1a;https://github.com/showlab/Image2Paragraph https:// 01 …

目标检测算法——YOLOv5/YOLOv7改进之结合​ASPP(空洞空间卷积池化金字塔)

&#x1f496;&#x1f496;>>>加勒比海带&#xff0c;QQ2479200884<<<&#x1f496;&#x1f496; &#x1f340;&#x1f340;>>>【YOLO魔法搭配&论文投稿咨询】<<<&#x1f340;&#x1f340; ✨✨>>>学习交流 | 温澜潮…

从BLIP-2到SAM视觉语义金字塔+ChatGPT= 把图片变文本段落, 8G显存即可Run

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【图像分割】微信技术交流群 作者&#xff1a;老大 |&#xff08;已授权转载&#xff09;编辑&#xff1a;CVer https://zhuanlan.zhihu.com/p/621503837 8G GPU显存即可以运…

问一下ChatGPT:DIKW金字塔模型

经常看到这张DIKW金字塔模型图&#xff0c;还看到感觉有点过份解读的图&#xff0c;后面又加上了insight&#xff0c;impact等内容。 Data&#xff1a;是数据&#xff0c;零散的、无规则的呈现到人们眼前&#xff0c;如果你只看到这些数字&#xff0c;如果没有强大的知识背景&a…

QCon: 工程师成长的金字塔思维

QCon 线下会议终于来了&#xff0c;但这次的分享有一些意外&#xff0c;不是性能、架构、内核、缓存&#xff0c;而不是AI实践相关的内容&#xff0c;论坛的主题是“工程师成长实践”&#xff0c;而我的topic 是“工程师成长的金字塔思维”。本以为这是一个非热门话题&#xff…

拉普拉斯金字塔

原文 高斯金字塔G0层下采样后为G1&#xff0c;用G0减去G1的上采样&#xff0c;就得到了拉普拉斯层L0. 高斯金字塔G1层上采样后与拉普拉斯金字塔L0层相加后就得到了G0层。 import numpy as np import cv2 as cv from matplotlib import pyplot as pltimg cv.imread(left_01.png…

微信称不会推出「已读」功能;马斯克宣布成立 AI 公司 xAI;GPT-4 架构曝光,有 1.8 万亿参数|极客头条

「极客头条」—— 技术人员的新闻圈&#xff01; CSDN 的读者朋友们早上好哇&#xff0c;「极客头条」来啦&#xff0c;快来看今天都有哪些值得我们技术人关注的重要新闻吧。 整理 | 梦依丹 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 一分钟速览新闻点&…

百度版本gactgpt即将来临,gpt人工智能机器横空出世

百度版本gactgpt即将来临&#xff0c;gpt人工智能机器横空出世&#xff0c;“一言”为定&#xff01;百度版ChatGPT确认&#xff01;李彦宏OKR曝光&#xff0c;率先应用于收索业务 gactCBT 大获&#xff0c;当下极有可能成为人工智能的 iPhone 时刻。为了在这场人工智能竞赛中…

解锁实盘交易,打通量化系统交易环节!股票量化分析工具QTYX-V2.3.9

前言 本期我们把股票量化分析工具QTYX的“交易”子页面给解锁了&#xff0c;这样一来&#xff0c;就打通了量化交易系统从分析到交易的完整过程&#xff0c;注意当前的QTYX版本升级到了2.3.9。 QTYX完整架构如下所示&#xff0c;其中包括了QTYX股票量化分析系统和实盘机器人两部…

自己做量化交易软件(43)小白量化实战16--利用小白量化金融模块在恒生PTrade交易系统(交易端)上仿大智慧指标回测及实战交易设计

自己做量化交易软件(43)小白量化实战16–利用小白量化金融模块在恒生PTrade交易系统(交易端)上仿大智慧指标回测及实战交易设计 量化产品PTrade(Personalise Trade)交易系统采用事件驱动式回测平台&#xff0c;与聚宽量化平台类似的量化框架&#xff0c;内置Ta-lib金融模块&am…

量化投资 | 量化交易平台工具汇总

量化投资必备手册&#xff0c;分享30个量化交易平台给你们&#xff0c;转需&#xff0c;不用谢&#xff01; 1. 掘金量化 量化交易系统官方网址&#xff1a;https://www.myquant.cn/ 2、国泰君安量化交易系统 量化交易系统网址&#xff1a;https://quant.gtja.com/ 3. 量化云…

初学Linux—解决开机卡在用户登录界面的问题

1.Linux关机之后开机界面卡在登录界面没有反应&#xff1b; 可能是我删除了某个文件… 2.解决办法&#xff1a; ctrlaltF2 ;切换终端 su root ;切换到超级用户 然后会弹出输入密码提示&#xff0c;直接输入超级用户的密码&#xff08;注意&#xff1a;linux中密码不会回显&am…

centos6.8开机一直卡在登录界面,无法登录

** **后面发现&#xff0c;问题出在&#xff0c;前几天配置的 java的jdk&#xff0c;还有mysql的环境变量上。 ** 解决问题的方法 使用CtrlAIt F3&#xff0c;竟然命令控制面板&#xff08;但是&#xff0c;进去后&#xff0c;你使用指令&#xff0c;比如&#xff0c;vi,ls -…

Ubuntu开机后卡在登陆界面进去不

系统&#xff1a;Ubuntu18.03 系统跑代码卡死了&#xff0c;导致鼠标键盘都用不了&#xff0c;直接强制关机后&#xff0c;卡在登陆界面进不去 步骤&#xff1a; 1. 系统启动后&#xff0c;在BIOS引导界面按"ESC"键进入选择菜单&#xff0c;选择第一个"*Ubun…

记一次绕过安全狗与360艰难提权

0x01 前言背景 端午短暂休息三天&#xff0c;复工之后朋友又丢给我一个Webshell&#xff0c;在打台球途中了解了一下这个奇怪的shell&#xff0c;说是无法执行命令&#xff0c;经过测试发现只能执行dir命令&#xff0c;确实奇怪&#xff0c;草草打了几局台球就回去拿起电脑开日…

为什么我骂360弱智 周鸿祎却说“谢谢”

好吧&#xff0c;我承认我标题党了&#xff01; 不过&#xff0c;有图有真相&#xff01; 事情的起因是我在360开发者平台&#xff0c;提交了我们的客户端“缘创派”&#xff0c;这是一个给互联网创业者找创业合伙人的应用。之前上传的是1.0版本&#xff0c;最近更新了功能更为…

曾遭周鸿祎全网封杀的 360 猛将 :草根打工到 36 岁身家上亿的逆袭!

作者 | 云游小生 来源 | 纯洁的微笑&#xff08;ID:keeppuresmile&#xff09; 猎豹六周年&#xff0c;傅盛在内部演讲&#xff1a; “有部电视剧叫《奋斗》&#xff0c;名字很好&#xff0c;帅哥靓女&#xff0c;青春励志。 但看了开头&#xff0c;我就看不下去了。作为一个奋…