241205_给自己的应用加上语音助手功能

241205_给自己的应用加上语音助手功能

前面我们自己做了一个网易云音乐,但每次都要去点点点显得有点麻烦,所以我就考虑添加一些语音助手的功能。

其实当前在日常windows使用中,我觉得也就音乐播放需要一个语音助手交互,其他的功能,要么太复杂,简单的声控无法实现,要么语音控制的效率太低,不如直接上手操作。

最简单的语音助手仅需要实现三个功能,本地语音转文本,根据文本内容提取关键词完成对应指令,播放“收到”“已完成”等语音,我们此处就实现这样的最简单的语音助手。

语音转文字

本地语音转文字我们使用vosk语音识别库实现。model使用本地的一个60m的小模型.

这里附模型链接: https://pan.baidu.com/s/1mY2VoRqjSwS6n4qj1pPZMA?pwd=8888

解压放在项目根目录就可以了

为了实现一个较好的唤醒效果,我们采用后台实时录音的方式。检测到声音的时候就进行转文字,但是因为环境噪音是一直存在的,此时我们就要给他设定一个阈值,当超过这个阈值时,我们才认为他是有效输入,才进行转文字输入。

def SaveWave(model):# 设置音频参数FORMAT = pyaudio.paInt16    # 音频流的格式RATE = 44100                # 采样率,单位HzCHUNK = 4000                # 单位帧THRESHOLDNUM = 10           # 静默时间,超过这个个数就保存文件THRESHOLD = 100             # 设定停止采集阈值audio = pyaudio.PyAudio()stream = audio.open(format=FORMAT,channels=1,rate=RATE,input=True,frames_per_buffer=CHUNK)frames = []print("开始录音...")count = 0while count < THRESHOLDNUM:data = stream.read(CHUNK, exception_on_overflow=False)np_data = np.frombuffer(data, dtype=np.int16)frame_energy = np.mean(np.abs(np_data))# print(frame_energy)# 如果能量低于阈值持续时间过长,则停止录音if frame_energy < THRESHOLD:count += 1elif count > 0:count -= 1frames.append(data)print("停止录音!")stream.stop_stream()stream.close()audio.terminate()rec = KaldiRecognizer(model, RATE)rec.SetWords(True)str_ret = ""for data in frames:if rec.AcceptWaveform(data):result = json.loads(rec.Result())if 'text' in result:str_ret += result['text']result = json.loads(rec.FinalResult())if 'text' in result:str_ret += result['text']str_ret = "".join(str_ret.split())return str_ret

执行命令

得到语音转文字的结果之后,我们就可指定对应执行的指令了,因为我们不需要联网去搜索结果,只需要定义我们自己能用到的指令就可以了,此处简单定义指令。

def weekup(mw):model = Model("vosk-model-cn-0.15")SetLogLevel(-1)while 1:res = SaveWave(model)if res != "" and res != None:print(res)if "小爱同学" in res:answer = "我在"answermethod(answer)if "聊天" in res:answer = "好的,请开始"answermethod(answer)from stt import run as stt_runresult=stt_run()if "打开" in res:app_name=res.replace("打开",'').strip()if app_name in dir_path:app_path=dir_path[app_name]import subprocesssubprocess.Popen(app_path)answer = "好的,已经为您打开了"answermethod(answer)if "歌" in res:from testyuncloud import yuncloudMWmw.playMusic()# print("播放歌曲")if "暂停" in res:mw.playMusic()if "上一首" in res:mw.prevMusic()if "下一首" in res:mw.nextMusic()

在这个方法中,我调用了一个answermethod方法,在这个方法中,我调用了百度的语音合成api,当然这里合成的都是一些简单的语音,你也可以直接自己录音,然后直接播放录音文件。就避免了调用api。

下面是answermethod以及百度语音合成api的调用。

def answermethod(answer):baidu_tts_test(answer)time.sleep(1)
# coding=utf-8
import sys
import json
import pygame
import time
import io
IS_PY3 = sys.version_info.major == 3
if IS_PY3:from urllib.request import urlopenfrom urllib.request import Requestfrom urllib.error import URLErrorfrom urllib.parse import urlencodefrom urllib.parse import quote_plus
else:import urllib2from urllib import quote_plusfrom urllib2 import urlopenfrom urllib2 import Requestfrom urllib2 import URLErrorfrom urllib import urlencodeAPI_KEY = ' ' # 这里和下面替换成你的百度语音合成服务api的key
SECRET_KEY = ' '# TEXT = "欢迎使用百度语音合成。"# 发音人选择, 基础音库:0为度小美,1为度小宇,3为度逍遥,4为度丫丫,
# 精品音库:5为度小娇,103为度米朵,106为度博文,110为度小童,111为度小萌,默认为度小美 
PER = 4
# 语速,取值0-15,默认为5中语速
SPD = 5
# 音调,取值0-15,默认为5中语调
PIT = 5
# 音量,取值0-9,默认为5中音量
VOL = 5
# 下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
AUE = 3FORMATS = {3: "mp3", 4: "pcm", 5: "pcm", 6: "wav"}
FORMAT = FORMATS[AUE]CUID = "123456PYTHON"TTS_URL = 'http://tsn.baidu.com/text2audio'class DemoError(Exception):pass"""  TOKEN start """TOKEN_URL = 'http://aip.baidubce.com/oauth/2.0/token'
SCOPE = 'audio_tts_post'  # 有此scope表示有tts能力,没有请在网页里勾选def fetch_token():print("fetch token begin")params = {'grant_type': 'client_credentials','client_id': API_KEY,'client_secret': SECRET_KEY}post_data = urlencode(params)if (IS_PY3):post_data = post_data.encode('utf-8')req = Request(TOKEN_URL, post_data)try:f = urlopen(req, timeout=5)result_str = f.read()except URLError as err:print('token http response http code : ' + str(err.code))result_str = err.read()if (IS_PY3):result_str = result_str.decode()print(result_str)result = json.loads(result_str)print(result)if ('access_token' in result.keys() and 'scope' in result.keys()):if not SCOPE in result['scope'].split(' '):raise DemoError('scope is not correct')print('SUCCESS WITH TOKEN: %s ; EXPIRES IN SECONDS: %s' % (result['access_token'], result['expires_in']))return result['access_token']else:raise DemoError('MAYBE API_KEY or SECRET_KEY not correct: access_token or scope not found in token response')"""  TOKEN end """def baidu_tts_test(text,PER=0,SPD=10,PIT=PIT,VOL=VOL):token = fetch_token()tex = quote_plus(text)  # 此处TEXT需要两次urlencodeprint(tex)params = {'tok': token, 'tex': tex, 'per': PER, 'spd': SPD, 'pit': PIT, 'vol': VOL, 'aue': AUE, 'cuid': CUID,'lan': 'zh', 'ctp': 1}  # lan ctp 固定参数data = urlencode(params)print('test on Web Browser' + TTS_URL + '?' + data)req = Request(TTS_URL, data.encode('utf-8'))has_error = Falsetry:f = urlopen(req)result_str = f.read()headers = dict((name.lower(), value) for name, value in f.headers.items())has_error = ('content-type' not in headers.keys() or headers['content-type'].find('audio/') < 0)except  URLError as err:print('asr http response http code : ' + str(err.code))result_str = err.read()has_error = Truesave_file = "error.txt" if has_error else 'result.' + FORMATwith open(save_file, 'wb') as of:of.write(result_str)if has_error:if (IS_PY3):result_str = str(result_str, 'utf-8')print("tts api  error:" + result_str)else:# 初始化pygamepygame.mixer.init()# 将音频数据加载到内存pygame.mixer.music.load(io.BytesIO(result_str))# 播放音频pygame.mixer.music.play()# # 防止程序立即退出# while pygame.mixer.music.get_busy():#     time.sleep(1)print("result saved as :" + save_file)

随后我要实现调整音量的功能,但是识别出来调整音量的百分比是汉字,无法直接去调整,此处就要建立汉字的数字到阿拉伯数字的映射。

from pypinyin import lazy_pinyindef hanzi_to_number_pinyin(hanzi_str):hnd = {'ling': 0, 'yi': 1, 'er': 2, 'san': 3, 'si': 4, 'wu': 5, 'liu': 6, 'qi': 7, 'ba': 8, 'jiu': 9,'shi': 10, 'bai': 100, 'qian': 1000, 'wan': 10000, 'yi': 100000000}pinyin_list = lazy_pinyin(hanzi_str)result = 0temp = 0for pinyin in pinyin_list:if pinyin in hnd:digit = hnd[pinyin]if digit >= 10:if temp == 0:temp = 1result += temp * digittemp = 0else:temp = temp * 10 + digitresult += tempreturn result

然后在关键词匹配的方法中实现调整音量

        if "音量" in res:volumn=res.split('百分之')[1]volumn=hanzi_to_number_pinyin(volumn)print(volumn)mw.volumeSet(volumn)

然后在我们的主方法里面,开启一个新线程,进行调用即可

image-20241205173514908

image-20241205173702632

以下是全部代码:

# weekupm.py
import json
import timeimport pyaudio
import numpy as np
from vosk import Model, KaldiRecognizer, SetLogLevel
from baidu_tts import baidu_tts_testdir_path={'浏览器': "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",'记事本': "C:\\Windows\\System32\\notepad.exe",'计算器': "C:\\Windows\\System32\\calc.exe"}
def SaveWave(model):# 设置音频参数FORMAT = pyaudio.paInt16    # 音频流的格式RATE = 44100                # 采样率,单位HzCHUNK = 4000                # 单位帧THRESHOLDNUM = 10           # 静默时间,超过这个个数就保存文件THRESHOLD = 100             # 设定停止采集阈值audio = pyaudio.PyAudio()stream = audio.open(format=FORMAT,channels=1,rate=RATE,input=True,frames_per_buffer=CHUNK)frames = []print("开始录音...")count = 0while count < THRESHOLDNUM:data = stream.read(CHUNK, exception_on_overflow=False)np_data = np.frombuffer(data, dtype=np.int16)frame_energy = np.mean(np.abs(np_data))# print(frame_energy)# 如果能量低于阈值持续时间过长,则停止录音if frame_energy < THRESHOLD:count += 1elif count > 0:count -= 1frames.append(data)print("停止录音!")stream.stop_stream()stream.close()audio.terminate()rec = KaldiRecognizer(model, RATE)rec.SetWords(True)str_ret = ""for data in frames:if rec.AcceptWaveform(data):result = json.loads(rec.Result())if 'text' in result:str_ret += result['text']result = json.loads(rec.FinalResult())if 'text' in result:str_ret += result['text']str_ret = "".join(str_ret.split())return str_retdef answermethod(answer):baidu_tts_test(answer)time.sleep(1)
def weekup(mw):model = Model("vosk-model-cn-0.15")SetLogLevel(-1)while 1:res = SaveWave(model)if res != "" and res != None:print(res)if "小爱同学" in res:answer = "我在"answermethod(answer)if "聊天" in res:answer = "好的,请开始"answermethod(answer)from stt import run as stt_runresult=stt_run()if "打开" in res:app_name=res.replace("打开",'').strip()if app_name in dir_path:app_path=dir_path[app_name]import subprocesssubprocess.Popen(app_path)answer = "好的,已经为您打开了"answermethod(answer)if "歌" in res:from testyuncloud import yuncloudMWmw.playMusic()# print("播放歌曲")if "暂停" in res:mw.playMusic()if "上一首" in res:mw.prevMusic()if "下一首" in res:mw.nextMusic()if "音量" in res:volumn=res.split('百分之')[1]volumn=hanzi_to_number_pinyin(volumn)print(volumn)mw.volumeSet(volumn)from pypinyin import lazy_pinyindef hanzi_to_number_pinyin(hanzi_str):hnd = {'ling': 0, 'yi': 1, 'er': 2, 'san': 3, 'si': 4, 'wu': 5, 'liu': 6, 'qi': 7, 'ba': 8, 'jiu': 9,'shi': 10, 'bai': 100, 'qian': 1000, 'wan': 10000, 'yi': 100000000}pinyin_list = lazy_pinyin(hanzi_str)result = 0temp = 0for pinyin in pinyin_list:if pinyin in hnd:digit = hnd[pinyin]if digit >= 10:if temp == 0:temp = 1result += temp * digittemp = 0else:temp = temp * 10 + digitresult += tempreturn result
# baidu_tts.py
# coding=utf-8
import sys
import json
import pygame
import time
import io
IS_PY3 = sys.version_info.major == 3
if IS_PY3:from urllib.request import urlopenfrom urllib.request import Requestfrom urllib.error import URLErrorfrom urllib.parse import urlencodefrom urllib.parse import quote_plus
else:import urllib2from urllib import quote_plusfrom urllib2 import urlopenfrom urllib2 import Requestfrom urllib2 import URLErrorfrom urllib import urlencodeAPI_KEY = '2I46jXf5CmlNycyOVAETigud'
SECRET_KEY = 'IJu44Y0K09y93ZQAOsObkJEhOEd1NBQa'# TEXT = "欢迎使用百度语音合成。"# 发音人选择, 基础音库:0为度小美,1为度小宇,3为度逍遥,4为度丫丫,
# 精品音库:5为度小娇,103为度米朵,106为度博文,110为度小童,111为度小萌,默认为度小美 
PER = 4
# 语速,取值0-15,默认为5中语速
SPD = 5
# 音调,取值0-15,默认为5中语调
PIT = 5
# 音量,取值0-9,默认为5中音量
VOL = 5
# 下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
AUE = 3FORMATS = {3: "mp3", 4: "pcm", 5: "pcm", 6: "wav"}
FORMAT = FORMATS[AUE]CUID = "123456PYTHON"TTS_URL = 'http://tsn.baidu.com/text2audio'class DemoError(Exception):pass"""  TOKEN start """TOKEN_URL = 'http://aip.baidubce.com/oauth/2.0/token'
SCOPE = 'audio_tts_post'  # 有此scope表示有tts能力,没有请在网页里勾选def fetch_token():print("fetch token begin")params = {'grant_type': 'client_credentials','client_id': API_KEY,'client_secret': SECRET_KEY}post_data = urlencode(params)if (IS_PY3):post_data = post_data.encode('utf-8')req = Request(TOKEN_URL, post_data)try:f = urlopen(req, timeout=5)result_str = f.read()except URLError as err:print('token http response http code : ' + str(err.code))result_str = err.read()if (IS_PY3):result_str = result_str.decode()print(result_str)result = json.loads(result_str)print(result)if ('access_token' in result.keys() and 'scope' in result.keys()):if not SCOPE in result['scope'].split(' '):raise DemoError('scope is not correct')print('SUCCESS WITH TOKEN: %s ; EXPIRES IN SECONDS: %s' % (result['access_token'], result['expires_in']))return result['access_token']else:raise DemoError('MAYBE API_KEY or SECRET_KEY not correct: access_token or scope not found in token response')"""  TOKEN end """def baidu_tts_test(text,PER=0,SPD=10,PIT=PIT,VOL=VOL):token = fetch_token()tex = quote_plus(text)  # 此处TEXT需要两次urlencodeprint(tex)params = {'tok': token, 'tex': tex, 'per': PER, 'spd': SPD, 'pit': PIT, 'vol': VOL, 'aue': AUE, 'cuid': CUID,'lan': 'zh', 'ctp': 1}  # lan ctp 固定参数data = urlencode(params)print('test on Web Browser' + TTS_URL + '?' + data)req = Request(TTS_URL, data.encode('utf-8'))has_error = Falsetry:f = urlopen(req)result_str = f.read()headers = dict((name.lower(), value) for name, value in f.headers.items())has_error = ('content-type' not in headers.keys() or headers['content-type'].find('audio/') < 0)except  URLError as err:print('asr http response http code : ' + str(err.code))result_str = err.read()has_error = Truesave_file = "error.txt" if has_error else 'result.' + FORMATwith open(save_file, 'wb') as of:of.write(result_str)if has_error:if (IS_PY3):result_str = str(result_str, 'utf-8')print("tts api  error:" + result_str)else:# 初始化pygamepygame.mixer.init()# 将音频数据加载到内存pygame.mixer.music.load(io.BytesIO(result_str))# 播放音频pygame.mixer.music.play()# # 防止程序立即退出# while pygame.mixer.music.get_busy():#     time.sleep(1)print("result saved as :" + save_file)

else ‘result.’ + FORMAT
with open(save_file, ‘wb’) as of:
of.write(result_str)

if has_error:if (IS_PY3):result_str = str(result_str, 'utf-8')print("tts api  error:" + result_str)
else:# 初始化pygamepygame.mixer.init()# 将音频数据加载到内存pygame.mixer.music.load(io.BytesIO(result_str))# 播放音频pygame.mixer.music.play()# # 防止程序立即退出# while pygame.mixer.music.get_busy():#     time.sleep(1)
print("result saved as :" + save_file)

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

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

相关文章

Navicat连接服务器MySQL

Navicat连接服务器MySQL 1. Navicat连接服务器MySQL2. 如何查看MySQL用户名和密码3. 修改MySQL登录密码4. 安装MySQL(Centos7)遇到错误和问题 1. error 1045 (28000): access denied for user ‘root’‘localhost’ (using password:yes) 1. Navicat连接服务器MySQL 选择数据…

得物新一代可观测性架构:海量数据下的存算分离设计与实践

一、引言 得物作为全球领先的潮流网购社区&#xff0c;日益增长的用户和数据带来了巨大的技术挑战。当前&#xff0c;得物的可观测性平台每天生成数PB级Trace数据和数万亿条Span记录&#xff0c;要求平台具备高效的实时处理能力和低成本的数据存储解决方案。 传统的存算一体架…

​ 基于51单片机的智能公交车报站系统GPS定位语音播报智能安全检测人数统计

功能介绍 以51单片机为控制核心.LCD12864可显示当前年月日&#xff0c;星期&#xff0c;时间&#xff0c; 当前站名&#xff0c;经纬度&#xff0c;是否连接GPS&#xff0c;自动/手动模式&#xff0c;自带GPS定位&#xff0c;可实时显示经纬度&#xff1b;通过DS1302时钟芯片…

Gitee配置SSH公钥

采用SSH协议同步Git仓库代码的好处就是高效。在配置好SSH公钥后&#xff0c;不需要每次操作都要输入用户名和密码&#xff08;主要针对命令行来说&#xff09;。 以我个人项目为例。 生成 SSH 公钥 1. 通过命令 ssh-keygen 生成 SSH Key&#xff1a; ssh-keygen -t ed25519…

CV(2)-插值和卷积

前言 仅记录学习过程&#xff0c;有问题欢迎讨论 看看年前可以学到哪。 频率&#xff1a; 灰度值变化程度的指标&#xff0c;是灰度再平面上的梯度幅值: 幅值&#xff1a; 是在一个周期内&#xff0c;交流电瞬时出现的最大绝对值&#xff0c;也是一个正弦波&#xff0c;波…

D362 php+mysql旅游服务网站的设计与实现 源码 配置 文档 全套资料

旅游服务网站的设计与实现 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 近几年&#xff0c;随着我国国民经济和信息技术的迅速发展&#xff0c;旅游项目的开发和建设&#xff0c;已是我国旅游业发展重要经济来源之一&#xff0c;我国旅游业近几年的…

python——列表

目录 一&#xff0c;选择题 二&#xff0c;判断题 三&#xff0c;列表的思维导图 一&#xff0c;选择题 1.已知列表 xlist(range(9))&#xff0c;那么执行之后&#xff0c;x的值为( D ) A. [1,3&#xff0c;5&#xff0c;7&#xff0c;9] B.[1,3,5&#xff0c;7] C.[0,1…

JAVA面试基础(总结了很多)

最近帮整理了一份JAVA的面试基础&#xff0c;不过很基础后面还回继续更新。 java的专业技能 2.1 java的基础部分 2.1.1 简单讲一下java的跨平台原理 由于各操作系统&#xff08;windows,liunx等&#xff09;支持的指令集&#xff0c;不是完全一致的。就会让我们的程序在不同的操…

基于SpringBoot的社区医院管理系统(代码+论文)

&#x1f389;博主介绍&#xff1a;Java领域优质创作者&#xff0c;阿里云博客专家&#xff0c;计算机毕设实战导师。专注Java项目实战、毕设定制/协助 &#x1f4e2;主要服务内容&#xff1a;选题定题、开题报告、任务书、程序开发、项目定制、论文辅导 &#x1f496;精彩专栏…

linux下使用gdb运行程序,查看程序崩溃原因

1.什么是gdb? gdb 是 GNU Debugger 的缩写&#xff0c;是一个功能强大的用于调试程序的开源调试器工具。它可以帮助开发人员诊断和解决程序中的错误、跟踪程序执行过程、查看变量的值等。gdb 支持多种编程语言&#xff0c;包括 C、C、Objective-C、Fortran 等&#xff0c;并可…

代发考试战报:12月近几日通过,题库已经更新至12月5号

代发考试战报&#xff1a;12月近几日通过&#xff0c;题库已经更新至12月5号&#xff0c;考试大约会遇到几个新题&#xff0c;就算遇到的新题全错&#xff0c;也不影响考试通过&#xff0c;HCIA-PM 12月2号上海通过&#xff0c;售前L3 H19-435 HCSP-Storage 存储 上海通过&…

使用Kubernetes部署MySQL+WordPress

目录 前提条件 部署MySQL和WordPress 编写yaml文件 应用yaml文件 存在问题及解决方案 创建PV(持久化卷) 创建一个PVC(持久化卷声明) 部署添加PVC 查看PV对应的主机存储 删除资源 查看资源 删除deployment和service 查看主机数据 删除PVC和PV 删除主机数据 前提条…

深入解析 Nginx:基础介绍到原理分析及案例实践

引言 Nginx&#xff08;“Engine-X”&#xff09;是一个高性能的 HTTP 和反向代理服务器&#xff0c;广泛应用于 Web 服务、负载均衡、API 网关、反向代理、静态资源服务器等多种场景。由于其高效的性能、低资源消耗和灵活的配置&#xff0c;Nginx 成为众多互联网公司、企业以…

Apache HTTPD多后缀解析漏洞

进入靶场 上来就是一个文件上传的功能 经过尝试&#xff0c;发现只有jpg&#xff0c;png&#xff0c;gif文件能上传上去&#xff0c;而题目又说了&#xff0c;这个是Apache的中间件&#xff0c;Apache文件解析漏洞涉及到一个Apache解析文件的特性&#xff0c;Apache默认一个文…

JavaScript(二)

1.JavaScript 操作符 2.JavaScript 流程控制 3.JavaScript 循环 4.JavaScript 字符串方法 5.JavaScript 数组方法 知识点一 操作符 变量声明 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Ti…

单链表---合并两个链表

将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 struct ListNode {int val;struct ListNode* next; }; w 方法一---不使用哨兵位 我们创建一个新链表用于合并两个升序链表&#xff0c; 将两个链表中最小的结点依次尾插到…

2024-12月akamai_2.0-sensor-data之cookie反爬分析详细教程(上)

目录 一、网址及目标数据二、分析接口反爬点&#xff08;akamai执行过程&#xff09;三、逆向分析参数sensor_data四、扣js算法代码加密详细步骤 一、网址及目标数据 文章原文 1、网站&#xff1a; https://www.dhl.com/cn-zh/home/tracking/tracking-supply-chain.html?sub…

【Docker】如何在Docker中配置防火墙规则?

Docker本身并不直接管理防火墙规则&#xff1b;它依赖于主机系统的防火墙设置。不过&#xff0c;Docker在启动容器时会自动配置一些iptables规则来管理容器网络流量。如果你需要更细粒度地控制进出容器的流量&#xff0c;你需要在主机系统上配置防火墙规则。以下是如何在Linux主…

煤矿 35kV 变电站 3 套巡检机器人 “上岗”,力破供电瓶颈

近日&#xff0c;杭州旗晟智能科技与甘肃某变电站配电室的三套智能巡检机器人线下测试顺利完成&#xff0c;并成功交付使用&#xff0c;这为电力运维工作注入了全新的活力与强大的技术支撑。 一、项目背景 甘肃某变电站总建筑面积1098平方米的变电站集变电、配电、监控等多功能…

[创业之路-170]:《BLM战略规划》- 领导力 - 战略制定 - 洞察力 (战略能力中最最核心的能力) - 市场洞察 -2- 看客户-B2B客户分析

目录 一、看客户概述 一、看客户的核心意义 二、看客户的具体内容 三、看客户的实践方法 四、看客户的重要性 二、2B客户的研究方法&#xff1a;研究客户的决策流程 2.1 客户的战略&#xff1a;财务、市场、运营组织 1、研究客户的决策流程 2、研究客户的战略 3、研究…