一个用语音控制视频播放的实现教程

发布时间:2025-02-11 01:12

智能电视语音控制:配合语音遥控器,可以实现语音搜索节目和操作电视。 #生活技巧# #居家生活技巧# #电器使用技巧# #电视遥控器调教#

背景:1、电影中语音播放视频的场景看起来很酷。2、生活中在跟着视频学习字、画、太极拳、舞蹈等时,手可能不方便按键盘,如果能语音控制视频,将会带来便利。

功能:用语音控制浏览器中的视频播放、暂停、倍速、回放、全屏。

硬件:语音识别模块(本例中为天问ASSR-ONE)、USB转串口、电脑

软件:天问Block、Pycharm python IDE、Global Speed浏览器插件

流程如下图

实现流程

步骤一:在浏览器中安装插件Global Speed。作用为设置快捷键来控制视频播放。快捷键需要设置为全局,这样才能在其它程序(或光标不在浏览器时)用快捷键控制视频。

Global Speed 设置

步骤二:编写语音识别模块的代码。将识别到的语音用串口发给电脑。

天问ASR-ONE 语音识别模块 图形化代码

步骤三:Python 代码。1、通过串口与语音模块通信。2、解析语音模块发送的串口数据帧。3、根据串口数据内容模拟点击快捷键。其中麻烦的是前两条。

3.1 串口基类

串口接收有两种方式。1、函数reciveUntil()在特定时间接收,比如电脑发一个查询指令给模块,设备会返回值,这种情况就用这个函数。2、一直处于接收状态,在本项目中,电脑不知道模块什么时候发数据帧,所以电脑要不断的查看接收缓冲区中有没有数据,代码位于线程函数rcv中。

# 定义串口类,基类 class MySerial: cyclicRcvFlag = 0 # 置1 在线程中循环接收帧,置0 不接收。默认不开启 isNewFrameFlag = 0 # 线程中是否有收到新帧的标识 newFrameData = '' # 新帧数据 frameStr = 'STR' # 帧头 frameEnd = '_EOF' # 帧尾 def __init__(self, com, baudRate, timeOut=4): self.com = com try: self.ser = serial.Serial(com, baudRate, timeout=timeOut) if self.ser.is_open: print(com + '连接成功(^-.-^)。波特率:' + str(self.ser.baudrate)) else: print(com + '未打开!!!(-_.._-)') except: print(com + '异常(-_.._-)') # 新建线程,用于监控是否有收到串口帧数据 self.thread1 = threading.Thread(target=self.rcv) # rcv 不能加括号 # 线程监控串口帧的处理函数 def rcv(self): data = '' print('串口监控线程开始运行') while True: if self.cyclicRcvFlag: data = data + self.ser.read(self.ser.in_waiting).decode() # 从串口中读数据并转换为str # 如果不包含起始帧将数据清空,避免无效数据过长 if (len(data) > len(self.frameStr)) and (self.frameStr not in data): data = '' continue # 如果data中包含起始帧和结束帧,则将更新帧数据 if (self.frameStr in data) and (self.frameEnd in data): indexStr = data.rfind(self.frameStr) # 从右向左检索,获取帧起始符的坐标 indexEnd = data.rfind(self.frameEnd) # 从右向左检索,获取帧结束符的坐标 self.newFrameData = data[indexStr:indexEnd + len(self.frameEnd)] # 提取帧数据 self.isNewFrameFlag = 1 # 将标志位置1 # print('串口接收线程收到数据:' + self.newFrameData) data = '' # print('串口监控线程运行中') time.sleep(0.1) # 可以有一个特别小的延时,否则CPU使用率较高 # 在中断中循环检测是否有串口数据,enable def cyclicRcvEn(self): self.cyclicRcvFlag = 1 # 在中断中循环检测是否有串口数据,disable def cyclicRcvDisEn(self): self.cyclicRcvFlag = 0

串口基类里面还封装了三个常用的函数,但是在此项目中没用到,放在这,备忘。

def send(self, data, suffix='\r\n'): """ :param data: 要发送的字符串 :param suffix: 后缀,默认为'回车换行’即\r\n :return: 无 """ data = str(data) + suffix self.ser.write(data.encode('utf-8')) def reciveUntil(self, endStr, waitAckOverTime=3): """ 读取串口中的数据,直到收到指定的结束符,或者超时退出 :param endStr: :param waitAckOverTime: 收到结束符的超时时间 :return: """ startTime = time.time() data = '' while True: endTime = time.time() data = data + self.ser.read(self.ser.in_waiting).decode() # 从串口中读数据并转换为str if endStr in data: return data if endTime - startTime > waitAckOverTime: # 超时处理 if len(data) == 0: print(datetime.datetime.now().strftime('%y-%m-%d %h_%m_%s.%f ') + self.ser.name + '应答超时') else: print(datetime.datetime.now().strftime('%y-%m-%d %h_%m_%s.%f ') + self.ser.name + '结束符超时') print('已经读到的值' + data + '中没有结束符' + endStr) return False def strIntercept(self, rawStr, startStr='read_succ', endStr='\r\n'): """ 提取一个字符串中两个特殊标记的中间字符串。例strIntercept('abcde','b','d')结果为'c' :param rawStr: 原字符串 :param startStr: 起始标记 :param endStr: 终止标记 :return: """ if (startStr not in rawStr) or (endStr not in rawStr): # 如果rawStr中没有起始或结束标记 print(datetime.datetime.now().strftime('%y-%m-%d %h_%m_%s.%f') + '\t' + self.ser.name + '字符串无法截取') print('原字符串' + rawStr + '中不同时含起始字符' + startStr + '\t结束字符' + endStr) return False startIndex = rawStr.find(startStr) + len(startStr) endIndex = rawStr.find(endStr) result = rawStr[startIndex:endIndex] return result

3.2 连接ASR模块

# 天问asr class ASR(MySerial): frameStr = 'STR' # TWEN-ASR 语音模块发送数据帧的帧头 frameEnd = '_EOF' # TWEN-ASR 语音模块发送数据帧的帧尾 def __init__(self, com, baudRate, timeOut=3): super().__init__(com, baudRate, timeOut) # 运行基类中的串口初始化 self.thread1.start() # 启动接收数据的线程 self.cyclicRcvEn() # enable 循环检测接收缓冲中的内容

在主函数中调用方法

# 连接天问asr tianWenASR = ASR('com5', 115200)

3.3 新建一个线程,当做主线程

# 快捷键功能 pythoncom.pumpmessages()把主线程占用了 # 新建一个线程,用于运行我的代码 class Thread1(threading.Thread): def __init__(self, name): threading.Thread.__init__(self) self.name = name def run(self): VD = 'VD' print('主线程开始运行') while 1: # print('主线程运行中') if tianWenASR.isNewFrameFlag == 1: # 当有新数据帧时 frameStr = tianWenASR.newFrameData # 获取数据帧内容 tianWenASR.isNewFrameFlag = 0 # 清数据帧标记位 if VD in frameStr: # 如果是视频播放的命令 cmdCtIdx = int(frameStr.find(VD)) + len(VD) # 获取命令内容在帧中的坐标 cmdCt = int(frameStr[cmdCtIdx:cmdCtIdx + 2]) # 获取命令内容 print('命令vd的内容为:' + str(cmdCt)) print('得到的快捷键为' + hotKeys[cmdCt][2] + '+' + hotKeys[cmdCt][3]) # 模拟点击快捷键 pyautogui.hotkey(hotKeys[cmdCt][2], hotKeys[cmdCt][3]) # 必需小写 time.sleep(0.1) # 可以有一个特别小的延时,否则CPU使用率较高 print(self.name, ' 线程已退出。')

3.4 主函数

看注释就够了

if __name__ == '__main__': print('\n程序开始运行~欢迎') # 从excel中读取视频播放的快捷键 app = xlwings.App(visible=False, add_book=False) # 打开excel软件 wb = app.books.open('视频播放快捷键表格.xlsx') # 打开excel文件 sheet = wb.sheets[0] hotKeys = sheet.range('a1:d12').value # 获取excel中的内容,存放的是点哪个快捷键!!! wb.close() # 关闭工作薄 app.quit() # 关闭excel软件 # 快捷键退出程序,按ESC退出程序,防止失控 hm = PyHook3.HookManager() # 创建hook管理器 hm.KeyDown = onKeyboardEvent # 将自定义函数绑定到键盘keydown事件中 hm.HookKeyboard() # 挂勾,键盘勾子 # 连接天问asr tianWenASR = ASR('com5', 115200) # 在mainThread线程中控制 mainThread = Thread1('mainThread') mainThread.start() print('快捷键退出程序开始运行') pythoncom.PumpMessages() # 这段代码必需放到最后,因为这之后的代码不会执行。 print('程序退出')

为防止失控,做了一个急停键,ESC。

# 急停快捷键按下后,停止模拟点击 def onKeyboardEvent(event): if str(event.Key) == 'Escape': print('紧急退出啦 ') os._exit(0) sys.exit() return True # 如果返回false,那么键盘消息不会继续传递,键盘不可用。

为了方便,我把快捷键放在一个excel表格中,每次程序运行时到表格中读数据,避免在代码中改来改去。

快捷键汇总到表格中

3.6 用到的模块

import datetime # 获取较精确的时间 import time # 延时函数 import serial # 串口通信 import pyautogui # 模拟点击快捷键 import PyHook3 # 监听键盘,当按esc时退出程序 import pythoncom import os # 退出程序 import sys # 退出程序 import xlwings # excel表格处理 import threading # 线程

参考文档

Python实现串口通信(pyserial)过程解析https://www.jb51.net/article/170801.htm 

Excel数据读存,获取行数列数。https://zhuanlan.zhihu.com/p/149878144

演示视频

网址:一个用语音控制视频播放的实现教程 https://www.yuejiaxmz.com/news/view/766396

相关内容

一种语音控制直播支架制造技术
吾爱视频播放器下载 吾爱视频播放器(全网VIP视频通杀,无广告播放) v1.2 免费绿色版 下载
知识类抖音短视频的传播现状与前景
视频语音识别文字
“辉视”智慧酒店互动视讯系统语音控制方案
中文版贾维斯语音助手Jarvis(电脑加强版Siri 已实现语音控制/自动播放下载音乐/天气播报/问路导航/搜索/计算器)
电视机如何匹配,才能用语音来控制,今天教你一招智能语音助手电子产品科技改变生活电视机
语音控制语音控制(语音控制:未来生活的便捷助手)
智能语音控制技术让每一个家电都能说会听
基于AVR的家庭语音控制器的软硬件实现

随便看看