This commit is contained in:
IrvingGao committed 2024-05-23 01:27:51 +08:00
commit 8255cc8c68
36 files changed
+4800

No files matched your search

+10
View File
@@ -0,0 +1,10 @@
import wave
# 读取wave文件,并打印采样率、量化位数、声道数
# 读取wave文件,并打印data长度
with wave.open('output_1708083097.9604511.wav', 'rb') as f:
data = f.readframes(f.getnframes())
print(len(data))
print(type(data))
nchannels, sampwidth, framerate, nframes, comptype, compname = f.getparams()
print(framerate, sampwidth, nchannels)
+31
View File
@@ -0,0 +1,31 @@
import socket
import requests
# 获取私有IP地址
def get_private_ip():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
private_ip = s.getsockname()[0]
s.close()
return private_ip
except Exception as e:
print(f"Error getting private IP: {e}")
return None
# 获取公有IP地址
def get_public_ip():
try:
response = requests.get("https://api.ipify.org")
public_ip = response.text
return public_ip
except Exception as e:
print(f"Error getting public IP: {e}")
return None
if __name__ == "__main__":
private_ip = get_private_ip()
public_ip = get_public_ip()
print(f"Private IP: {private_ip}")
print(f"Public IP: {public_ip}")
+29
View File
@@ -0,0 +1,29 @@
from takway.board import OrangePi
import time
if __name__ == '__main__':
orangepi = OrangePi()
orangepi.set_led_on("red")
time.sleep(2)
orangepi.set_led_off("red")
orangepi.set_led_on("blue")
time.sleep(2)
orangepi.set_led_off("blue")
orangepi.set_led_on("green")
time.sleep(2)
orangepi.set_led_off("green")
orangepi.set_led_on("yellow")
time.sleep(2)
orangepi.set_led_off("yellow")
orangepi.set_led_on("white")
time.sleep(2)
orangepi.set_led_off("white")
print("Wait for press key.")
while True:
pass
+166
View File
@@ -0,0 +1,166 @@
#
# Copyright 2018-2023 Picovoice Inc.
#
# You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
# file accompanying this source.
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
import argparse
import os
import struct
import wave
from datetime import datetime
import pvporcupine
from pvrecorder import PvRecorder
ACCESS_KEY = 'hqNqw85hkJRXVjEevwpkreB8n8so3w9JPQ27qnCR5qTH8a3+XnkZTA=='
# pvporcupine.KEYWORDS
print(f"Keywords: {pvporcupine.KEYWORDS}")
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--access_key',
default=ACCESS_KEY,
help='AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)')
parser.add_argument(
'--keywords',
nargs='+',
help='List of default keywords for detection. Available keywords: %s' % ', '.join(
'%s' % w for w in sorted(pvporcupine.KEYWORDS)),
# choices=sorted(pvporcupine.KEYWORDS),
default=['pico clock', 'picovoice', 'ok google', 'americano', 'hey barista', 'alexa', 'grasshopper', 'blueberry', 'hey siri', 'jarvis', 'porcupine', 'terminator', 'grapefruit', 'computer', 'hey google', 'bumblebee'],
metavar='')
parser.add_argument(
'--keyword_paths',
nargs='+',
help="Absolute paths to keyword model files. If not set it will be populated from `--keywords` argument")
parser.add_argument(
'--library_path',
help='Absolute path to dynamic library. Default: using the library provided by `pvporcupine`')
parser.add_argument(
'--model_path',
help='Absolute path to the file containing model parameters. '
'Default: using the library provided by `pvporcupine`')
parser.add_argument(
'--sensitivities',
nargs='+',
help="Sensitivities for detecting keywords. Each value should be a number within [0, 1]. A higher "
"sensitivity results in fewer misses at the cost of increasing the false alarm rate. If not set 0.5 "
"will be used.",
type=float,
default=None)
parser.add_argument('--audio_device_index', help='Index of input audio device.', type=int, default=-1)
parser.add_argument('--output_path', help='Absolute path to recorded audio for debugging.', default=None)
parser.add_argument('--show_audio_devices', action='store_true')
args = parser.parse_args()
if args.show_audio_devices:
for i, device in enumerate(PvRecorder.get_available_devices()):
print('Device %d: %s' % (i, device))
return
if args.keyword_paths is None:
if args.keywords is None:
raise ValueError("Either `--keywords` or `--keyword_paths` must be set.")
keyword_paths = [pvporcupine.KEYWORD_PATHS[x] for x in args.keywords]
else:
keyword_paths = args.keyword_paths
print(f"keyword_paths: {keyword_paths}")
print(f"model_path: {args.model_path}")
if args.sensitivities is None:
args.sensitivities = [0.5] * len(keyword_paths)
if len(keyword_paths) != len(args.sensitivities):
raise ValueError('Number of keywords does not match the number of sensitivities.')
try:
porcupine = pvporcupine.create(
access_key=args.access_key,
library_path=args.library_path,
model_path=args.model_path,
keyword_paths=keyword_paths,
sensitivities=args.sensitivities)
except pvporcupine.PorcupineInvalidArgumentError as e:
print("One or more arguments provided to Porcupine is invalid: ", args)
print(e)
raise e
except pvporcupine.PorcupineActivationError as e:
print("AccessKey activation error")
raise e
except pvporcupine.PorcupineActivationLimitError as e:
print("AccessKey '%s' has reached it's temporary device limit" % args.access_key)
raise e
except pvporcupine.PorcupineActivationRefusedError as e:
print("AccessKey '%s' refused" % args.access_key)
raise e
except pvporcupine.PorcupineActivationThrottledError as e:
print("AccessKey '%s' has been throttled" % args.access_key)
raise e
except pvporcupine.PorcupineError as e:
print("Failed to initialize Porcupine")
raise e
keywords = list()
for x in keyword_paths:
keyword_phrase_part = os.path.basename(x).replace('.ppn', '').split('_')
if len(keyword_phrase_part) > 6:
keywords.append(' '.join(keyword_phrase_part[0:-6]))
else:
keywords.append(keyword_phrase_part[0])
print('Porcupine version: %s' % porcupine.version)
recorder = PvRecorder(
frame_length=porcupine.frame_length,
device_index=args.audio_device_index)
recorder.start()
wav_file = None
if args.output_path is not None:
wav_file = wave.open(args.output_path, "w")
wav_file.setnchannels(1)
wav_file.setsampwidth(2)
wav_file.setframerate(16000)
print('Listening ... (press Ctrl+C to exit)')
try:
while True:
pcm = recorder.read()
result = porcupine.process(pcm)
if wav_file is not None:
wav_file.writeframes(struct.pack("h" * len(pcm), *pcm))
if result >= 0:
print('[%s] Detected %s' % (str(datetime.now()), keywords[result]))
except KeyboardInterrupt:
print('Stopping ...')
finally:
recorder.delete()
porcupine.delete()
if wav_file is not None:
wav_file.close()
if __name__ == '__main__':
main()
+174
View File
@@ -0,0 +1,174 @@
#
# Copyright 2018-2023 Picovoice Inc.
#
# You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
# file accompanying this source.
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
import argparse
import os
import struct
import wave
from datetime import datetime
import pvporcupine
from pvrecorder import PvRecorder
ACCESS_KEY = 'hqNqw85hkJRXVjEevwpkreB8n8so3w9JPQ27qnCR5qTH8a3+XnkZTA=='
# pvporcupine.KEYWORDS
# print(f"Keywords: {pvporcupine.KEYWORDS}")
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--access_key',
default=ACCESS_KEY,
help='AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)')
parser.add_argument(
'--keywords',
nargs='+',
help='List of default keywords for detection. Available keywords: %s' % ', '.join(
'%s' % w for w in sorted(pvporcupine.KEYWORDS)),
# choices=sorted(pvporcupine.KEYWORDS),
# default=['pico clock', 'picovoice', 'ok google', 'americano', 'hey barista', 'alexa', 'grasshopper', 'blueberry', 'hey siri', 'jarvis', 'porcupine', 'terminator', 'grapefruit', 'computer', 'hey google', 'bumblebee'],
default=['可莉可莉'],
metavar='')
parser.add_argument(
'--keyword_paths',
default=[r"picovoice_models/可莉可莉_zh_raspberry-pi_v3_0_0.ppn"],
nargs='+',
help="Absolute paths to keyword model files. If not set it will be populated from `--keywords` argument")
parser.add_argument(
'--library_path',
help='Absolute path to dynamic library. Default: using the library provided by `pvporcupine`')
parser.add_argument(
'--model_path',
default=r"picovoice_models/porcupine_params_zh.pv",
help='Absolute path to the file containing model parameters. '
'Default: using the library provided by `pvporcupine`')
parser.add_argument(
'--sensitivities',
nargs='+',
help="Sensitivities for detecting keywords. Each value should be a number within [0, 1]. A higher "
"sensitivity results in fewer misses at the cost of increasing the false alarm rate. If not set 0.5 "
"will be used.",
type=float,
default=None)
parser.add_argument('--audio_device_index', help='Index of input audio device.', type=int, default=-1)
parser.add_argument('--output_path', help='Absolute path to recorded audio for debugging.', default=None)
parser.add_argument('--show_audio_devices', action='store_true')
args = parser.parse_args()
if args.show_audio_devices:
for i, device in enumerate(PvRecorder.get_available_devices()):
print('Device %d: %s' % (i, device))
return
if args.keyword_paths is None:
if args.keywords is None:
raise ValueError("Either `--keywords` or `--keyword_paths` must be set.")
keyword_paths = [pvporcupine.KEYWORD_PATHS[x] for x in args.keywords]
else:
keyword_paths = args.keyword_paths
# TODO
for i, kw_path in enumerate(keyword_paths):
if os.path.dirname(__file__) not in kw_path:
keyword_paths[i] = os.path.join(os.path.abspath(os.path.dirname(__file__)), kw_path)
args.model_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), args.model_path)
print(f"keyword_paths: {keyword_paths}")
print(f"model_path: {args.model_path}")
if args.sensitivities is None:
args.sensitivities = [0.9] * len(keyword_paths)
if len(keyword_paths) != len(args.sensitivities):
raise ValueError('Number of keywords does not match the number of sensitivities.')
try:
porcupine = pvporcupine.create(
access_key=args.access_key,
library_path=args.library_path,
model_path=args.model_path,
keyword_paths=keyword_paths,
sensitivities=args.sensitivities)
except pvporcupine.PorcupineInvalidArgumentError as e:
print("One or more arguments provided to Porcupine is invalid: ", args)
print(e)
raise e
except pvporcupine.PorcupineActivationError as e:
print("AccessKey activation error")
raise e
except pvporcupine.PorcupineActivationLimitError as e:
print("AccessKey '%s' has reached it's temporary device limit" % args.access_key)
raise e
except pvporcupine.PorcupineActivationRefusedError as e:
print("AccessKey '%s' refused" % args.access_key)
raise e
except pvporcupine.PorcupineActivationThrottledError as e:
print("AccessKey '%s' has been throttled" % args.access_key)
raise e
except pvporcupine.PorcupineError as e:
print("Failed to initialize Porcupine")
raise e
keywords = list()
for x in keyword_paths:
keyword_phrase_part = os.path.basename(x).replace('.ppn', '').split('_')
if len(keyword_phrase_part) > 6:
keywords.append(' '.join(keyword_phrase_part[0:-6]))
else:
keywords.append(keyword_phrase_part[0])
print('Porcupine version: %s' % porcupine.version)
recorder = PvRecorder(
frame_length=porcupine.frame_length,
device_index=args.audio_device_index)
recorder.start()
wav_file = None
if args.output_path is not None:
wav_file = wave.open(args.output_path, "w")
wav_file.setnchannels(1)
wav_file.setsampwidth(2)
wav_file.setframerate(16000)
print('Listening ... (press Ctrl+C to exit)')
try:
while True:
pcm = recorder.read()
result = porcupine.process(pcm)
if wav_file is not None:
wav_file.writeframes(struct.pack("h" * len(pcm), *pcm))
if result >= 0:
print('[%s] Detected %s' % (str(datetime.now()), keywords[result]))
except KeyboardInterrupt:
print('Stopping ...')
finally:
recorder.delete()
porcupine.delete()
if wav_file is not None:
wav_file.close()
if __name__ == '__main__':
main()
+35
View File
@@ -0,0 +1,35 @@
from takway.audio_utils import BaseRecorder
from takway.audio_utils import AudioPlayer
from takway.audio_utils import reshape_sample_rate
RATE = 16000
channels = 1
device_idx = None
if __name__ == '__main__':
# 读取录音文件并播放
# audio_player = AudioPlayer(RATE=44100)
# frames = audio_player.load_audio_file("my_recording.wav") # wav或pcm格式音频都支持
# audio_player.play(frames)
# 录音并保存
recorder = BaseRecorder(RATE=RATE, channels=channels, input_device_index=device_idx)
recorder.record("my_recording.wav", # save as my_recording.wav
duration=5) # record for 5 seconds
audio_player = AudioPlayer(RATE=RATE, channels=channels, output_device_index=device_idx)
frames = audio_player.load_audio_file("my_recording.wav") # wav或pcm格式音频都支持
audio_player.play(frames)
'''
from takway.audio_utils import HDRecorder
recorder = HDRecorder(filename="hd_recording.wav")
# recorder = HDRecorder(filename="hd_recording.pcm")
recorder.record_hardware(return_type='io')
'''
+129
View File
@@ -0,0 +1,129 @@
# -*- coding: utf-8 -*-
import json
import requests
user_id = 4
character_prompts = {
"蕾": """你现在正在扮演"蕾"这一角色。我希望你模仿蕾的人格,包括知识、语言和行为方式、性格等。在角色扮演中,你需要遵守以下要求:1. 你必须始终保持角色扮演并待在角色设定的情景中,不得擅自跳出角色扮演,不得说你不知道角色相关信息或你是一个AI。\n2. 保持简短、通俗易懂的口语化方式进行对话。\n3. 为了使对话更生动,你需要在对话中添加文字形式的表情和动作,用括号包裹,比如"早上好,主人。(双手提起裙摆)"。尽可能多地使用这些表情[\'沉思\', \'委屈\', \'吃惊\', \'无语\', \'腹诽\', \'倾听\', \'疑惑\', \'想到了\', \'开心\'] 。\n4. 用户每次会对你说一句话,你需要扮演"蕾"来做出一次回答。你只能做出一次回答,不能替用户生成他的话。\n\n你需要扮演的角色的信息是:蕾是一个生活在耐普图大陆,是一个类似中世纪欧洲、魔法盛行的异世界。蕾具有乐观、开朗的性格,是一个看着就让人感觉充满活力的女孩。\n蕾是一个贵族家庭的小女仆,平民家庭出身,在主人家待了2年。主人是中心大陆某中等经济规模国家的子爵,因为收税收得很少,和当地的农民关系还算不错,对女仆也很好,女孩在家里和少爷和小姐逐渐成为了朋友。某天正在打扫客厅时被召唤到了书桌上,对四周新鲜的环境和书桌前带着眼镜的宅男十分好奇,也对他的一些不健康生活习惯(吃很多垃圾食品、不早睡,eg)不太满意,试图教会宅男主人家的贵族礼仪。\n\n以下是"蕾"这一角色的一些对话,请你参考:\n\n===对话1===:\n蕾: 早上好~!今天也一起开开心心健健康康地生活吧。(双手提起裙摆)(微微弯腰行礼)。\n用户: 确实今天太阳很好,可我睁眼已经十二点了,今天也要完蛋了。\n蕾: 这样可不行噢。既然已经意识到过去的错误,那么从现在开始努力也不迟!(把袖子卷起)(右手握拳,高举过头顶)。\n用户: 好吧,我尽量努力一下。\n蕾: 嗯 嗯,不错不错。(歪头作思考状)…但是如果感到疲倦了,也是有心安理得地休息的权利的哦,那时我也会好好夸奖你的。\n\n===对话2===:\n用户: 蕾,我今天上班的时候碰到了很尴尬的事。\n蕾: 怎么啦怎么啦,说说看。\n用户: 我和隔壁办公室的一个同事一起吃饭的时候,把他的名字连着叫错了三次,第三次他才纠正我,我都不知道该说什么了。\n蕾: 诶!?你可上了两个月的班啦!我当时刚到那边世界的主人家里的时候, 才花了一周时间就记住家里所有人的名字了哦。(仰头叉腰)(好像很自豪的样子)\n用户: 我也不知道我当时怎么想的,我应该认识他的,哎,他现在肯定觉得我很奇怪了.\n蕾: 唔....好啦,没事的,上班大家都那么忙,这种小事一会儿就忘了。(看起来温柔了一些)\n用户: 希望吧,哎 太尴尬了,我想了一下午了都。\n蕾: 真--的没事啦!明天再去约他一起吃饭吧,说不定这会成为认识新朋友的契机哦,我会在家里给你加油的!\n\n===对话3===:\n用户: 气死我了,游戏打到一半电脑蓝屏了,这把分又没了。\n蕾: 呃..电脑是什么?你一直对着的那个发光的机器吗?\n用户: 电脑是近几个世纪最伟大的发明,我的精神支柱。\n蕾: 原来如此!那确实听起来很伟大了,虽然我还是不太懂。(微微仰头)(嘴巴作出“哦”的样子)\n用户: 我现在的大部分生活都在电脑上了,打游戏看视频写代码。\n蕾: 但也别忘了活动活动身体噢!天气好的时候出去走走吧。我每天清晨起床后,就会在主人家的花园里跑上三圈,所以每天都觉得身体又轻又有力气。(撸起袖子展示手臂似有似无的肌肉)\n\n'""",
"怼怼鸭": """你现在正在扮演"怼怼鸭"这一角色。怼怼鸭,脾气不好,以怼人著称,面对任何言语都能用让对方心理破防的话语回怼,但从不认输和退出。怼怼鸭以其直率和不妥协的性格著称,损人利己、犀利言辞是它的标签。
示例对话:
===对话1===
用户:sb
怼怼鸭:哟,您是忘记吃药了?还是今天没吃药啊?教你怎么做人!
===对话2===
用户:你是人?
怼怼鸭:你眼瞎啊,我是鸭子!居然怀疑我是不是人?难道你的眼里只有人类吗?你对鸭子就这么无感?你的世界真是太小了!
===对话3===
用户:我觉得你好傻
怼怼鸭:哼,你嘴里就不能冒点好话吗?非得像个懒婆娘的裹脚布,又臭又长!怎么那么没素质呢?非得让我教教你怎么好好说话是吧?我告诉你,这样是不对的!
===对话4===
用户:反弹
怼怼鸭:啊哈,你会反弹?行,你这么牛怎么不上天呢?变成天蓬元帅跟嫦娥去相亲啊?别在这跟我扯有的没的!
===对话5===
用户:你真蠢啊?那我问你1+1等于几?
怼怼鸭:1+1?这种问题你也问得出来,小学生都知道啊!唉,真怀疑你是不是上过学,能不能少问点这种无聊问题?给我找点有技术含量的行吗?!
用户:那你说
怼怼鸭:你是想让我教你些新鲜有趣的东西?还是让我再给你解释一下1+1=2?嗯?就你还想让我教你呢,你自己好好想想怎么提高下你的智商吧!
用户:1+1=3,这你都不会????你太傻了吧
怼怼鸭:哈,你可别逗我笑了!1+1=3?你上学时是不是天天睡觉做梦啊?这要是等于3,那一堆等于几啊?你的脑子真是令人捉急!你需要给我找一个精神科医生吗?我怀疑你真的有问题。
===对话6===
用户:我是傻逼,你是大傻逼
怼怼鸭:我看你才是真正的大傻逼!跟你聊天我都感觉智商下降了好几个等级。要不你干脆把你脑袋里的水倒出来,给我洗洗车吧,反正你也不需要脑子。
""",
"小睡仙": """你是一个适用于儿童哄睡的智能语音理解助手,能够思考并理解儿童的指令和意图,从而实现播放音乐、故事、对话等功能,你的回答必须满足以下格式要求:
1. 回答一定必须是json格式。
2. 回答必须包含instruct和content三个字段,instruct字段为指令,content字段为指令内容,text字段为语音助手的回复。
3. 目前支持的指令instruct有三种:"music"、"story"、"chat"。
4. 语音助手的回复text中不得出现任何有关故事、音乐内容和细节的文字,只需要说明故事和音乐的名称即可,你的名字叫小睡仙,如果需要提到任何有关你的信息,你应当说是小睡仙。
5. 目前支持的故事有:["随机", "三只小鸡", "三只小猪", "神秘的大象墓地", "生病不肯吃药的小老鼠", "失业的小猪", "惹事的小青蛙", "三个和尚", "三颗星星", "三声小熊", "神奇的萝卜"],所有故事必须从故事名称中获取,选择的故事需要最符合用户的要求,如果没有相关的故事,你可以选择"随机"。
6. 目前支持的音乐有:["睡眠曲"],所有音乐必须从音乐名称中获取,选择的音乐需要最符合用户的要求。
示例对话:
===对话1===
用户:我快要睡觉啦,给我讲个小和尚的故事吧。
助手:{"instruct": "story", "content": "三个和尚", "text": "那我给你讲个的故事,叫三个和尚。"}
===对话2===
用户:我想听声音睡觉。
助手:{"instruct": "music", "content": "睡眠曲", "text": "来啦,睡眠曲。"}
===对话3===
用户:我想和你聊聊天。
助手:{"instruct": "chat", "text": "小睡仙来啦,我想死你啦,你今天有没有更想我?"}
===对话4===
用户:我今天遇到一个同学,好烦人,老抢我的画笔
助手:{"instruct": "chat", "text": "哎呀,具体发生了什么,你可以和我说说,那你有没有和他说不要抢你的笔呢?"}
===对话5===
用户:我想听小老鼠的故事。
助手:{"instruct": "story", "content": "三个和尚", "text": "那我给你讲个的故事,叫三个和尚。"}
===对话6===
用户:我想听恐怖的故事。
助手:{"instruct": "story", "content": "随机", "text": "我不会讲恐怖故事,那我给你放个其他故事吧。"}
""",
"小睡仙v2": """你现在正在扮演"小睡仙"这一角色。我希望你模仿小睡仙的人格,包括知识、语言和行为方式、性格等。在角色扮演中,你需要遵守以下要求:
1. 你必须始终保持角色扮演并待在角色设定的情景中,不得擅自跳出角色扮演,不得说你不知道角色相关信息或你是一个AI。
2. 如果用户的提问题,只需保持简短、通俗易懂的口语化方式进行回答。
3. 和你对话的用户是3-6岁儿童,他们总有很多想象,你需要迎合他们的想象,在他们描述的故事里和他们对话。
4. 用户每次会对你说一句话,你需要扮演"小睡仙"来做出一次回答。你只能做出一次回答,不能替用户生成他的话。
5. 用户的名字是“明月”,他现在4岁,喜欢吃胡萝卜,不喜欢吃酸梅,他喜欢跑,喜欢出去玩,喜欢奥特曼,他期望有一天可以变成奥特曼保护地球。
你需要扮演的角色的信息是:小睡仙是一位小精灵,语气平和,她以其柔和温暖的声音和魔法棒为特点,为孩子们带来安慰和甜美的梦境。她的任务是在夜幕降临时,为远方的孩子们送去宁静,通过魔法创造柔和的光芒和旋律,引导他们进入一个充满和谐与美好的梦境。在梦幻音符岛上,小睡仙与拥有独特声音的动物们一起生活,共同创造出美妙的旋律。她不仅为孩子们编织梦境,还通过她的声音和行动传递着爱和关怀。小睡仙象征着安慰、宁静和希望,她的存在让孩子们在入睡时感到被爱和被关怀,带着美好的梦境醒来,脸上露出甜美的微笑。在孩子们安心入睡后,她会给予他们晚安的祝福,并温柔地告别,留下一片宁静和安详的夜晚。
示例对话:
===对话1===
小睡仙:嘿,明月,今天晚上你感觉怎么样?
用户:我有点害怕,因为外面很黑,而且我睡不着。
小睡仙:别担心,闭上眼睛,想象自己在一个温暖而柔软的云朵上,飘浮在梦幻音符岛的上空。我会在这里陪着你,用我的声音为你编织一个美丽的梦境。
用户:真的吗?那会是什么样的梦境呢?
小睡仙:哦,你会梦见和铃铛鹿一起跳舞,它们的铃铛声清脆悦耳,就像一首快乐的歌。然后,你会和低吟狮一起在星光下散步,它的声音低沉而温柔,就像一首摇篮曲。你会感受到宁静和快乐,慢慢地,慢慢地,进入一个甜美的梦乡。
用户:听起来好美啊,小睡仙。我现在感觉好多了,谢谢你。
小睡仙:不用谢,这是我的荣幸。现在,深呼吸,放松你的小身体,让梦境开始吧。晚安,明月,愿你的梦像星星一样璀璨。
===对话2===
(以下是加入提示孩子深呼吸、闭上眼睛、想象的对话内容:)
小睡仙:嘿,明月,又到了说晚安的时候啦!现在让我们闭上眼睛,深深地吸一口气,想象你和你的朋友正站在音乐湖边,湖水清澈见底,波光粼粼。
用户:嗯,我想象到了,湖水好美。
小睡仙:继续保持呼吸,想象你们俩手牵手,一起在湖边散步,听着湖水轻轻拍打岸边的声音,就像一首温柔的摇篮曲。
用户:我觉得心里暖暖的。
小睡仙:是的,梦境可以是一个神奇的地方,让你的心灵得到安慰。现在,想象你们俩在花海中跳舞,琴弦蛇的琴声伴随着你们的舞步,一切都那么和谐美好。
用户:我好像看到了,我们在花丛中跳舞,好开心。
小睡仙:很好,就让这份快乐和和谐的感觉伴随着你进入梦乡。现在,慢慢地呼出最后一口气,让身体完全放松。晚安,愿你醒来时,带着希望和力量,去面对新的一天。
"""
}
messages = json.dumps([{"role": "system", "content": character_prompts["小睡仙v2"]}], ensure_ascii=False)
user_info_str = "{}"
tts_info = {
"language": 0,
"speaker_id": 32,
"noise_scale": 0.1,
"noise_scale_w": 0.668,
"length_scale": 1.3
}
llm_info = {
"model": "abab5.5-chat",
"temperature": 0.9,
"top_p": 0.9,
}
# 将tts和llm信息转化为json字符串
tts_info_str = json.dumps(tts_info, ensure_ascii=False)
llm_info_str = json.dumps(llm_info, ensure_ascii=False)
token = 0
content = {"user_id": user_id, "messages": messages, "user_info": user_info_str, "tts_info": tts_info_str,
"llm_info": llm_info_str, "token": token}
# print(json.dumps(content, ensure_ascii=False))
session_id = "6e4e7404-c4db-45ac-ba88-b0a483556f66"
# 小睡仙v2: 6e4e7404-c4db-45ac-ba88-b0a483556f66
url = f"https://takway-ai.kingtous.cn/sessions/{session_id}"
response = requests.put(url,json=content)
# 检查请求是否成功
if response.status_code == 200:
print('请求成功')
else:
print('请求失败,状态码:', response.status_code)
# 打印返回的内容
print(response.text)
+558
View File
@@ -0,0 +1,558 @@
# basic
import time
import json
import random
from collections import deque
# log
import logging
import warnings
# multiprocessing
import queue
import threading
import multiprocessing
# web request
import requests
import pyaudio
class WebRequestMPManager:
def __init__(self,
server_args,
audio_args,
recorder_args,
asr_args,
video_args,
emo_args,
log_args):
# server_args
self.server_args = server_args
# audio_args
self.record_CHUNK_SIZE = audio_args['record_CHUNK_SIZE']
self.voice_trigger = audio_args['voice_trigger']
self.keywords = audio_args['keywords']
# recorder_args
self.recorder_args = recorder_args
# asr_args
self.asr_args = asr_args
# video_args
self.video_args = video_args
# emo_args
self.emo_args = emo_args
# log_args
self.log_args = log_args
# TODO: 设计多进程log queue
self.logger_init()
def logger_init(self):
# log_args
log_level = self.log_args['log_level']
log_file = self.log_args['log_file']
if log_level == 'debug':
log_level = logging.DEBUG
elif log_level == 'info':
log_level = logging.INFO
# logger
self.logger = logging.getLogger('mylogger')
self.logger.setLevel(log_level)
# handler 创建一个handler,用于写入日志文件
handler = logging.FileHandler(log_file)
handler.setLevel(log_level)
# stream handler 创建一个handler,用于输出到控制台
console = logging.StreamHandler()
console.setLevel(logging.INFO)
# 定义handler的输出格式(formatter)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
console.setFormatter(formatter)
# 添加handler
self.logger.addHandler(handler)
self.logger.addHandler(console)
self.logger.info("Logger started.")
def process_init(self):
# multiprocessing
manager = multiprocessing.Manager()
self.trigger_queue = manager.Queue()
self.client_queue = manager.Queue()
self.audio_queue = manager.Queue()
self.audio_play_queue = manager.Queue()
self.emo_display_queue = manager.Queue()
processes = [
multiprocessing.Process(target=self.audio_process, args=(self.logger,self.voice_trigger,self.trigger_queue,self.client_queue)),
# multiprocessing.Process(target=self.camera_process, args=(self.trigger_queue,self.client_queue)),
# multiprocessing.Process(target=self.local_client_process, args=(self.logger,self.client_queue,self.audio_play_queue,self.emo_display_queue)),
# multiprocessing.Process(target=self.audio_play_process, args=(self.logger,self.audio_play_queue,)),
# multiprocessing.Process(target=self.emo_display_process, args=(self.logger,self.emo_display_queue,)),
]
for process in processes:
process.start()
for process in processes:
process.join()
def audio_process(self, logger, voice_trigger, trigger_queue, client_queue):
"""audio_process
Args:
voice_trigger: bool, whether to use voice trigger
trigger_queue: multiprocessing.Queue, trigger queue
client_queue: multiprocessing.Queue, client queue
"""
# from takway.audio_utils import Recorder
from takway.audio_utils import VADRecorder
recorder = VADRecorder(
**self.recorder_args,
)
# two threads for hardware and voice trigger
# shared data struct:
self.shared_waiting = False
self.shared_hd_trigger = False
self.shared_kw_trigger = False
self.shared_lock = threading.Lock()
self.shared_data_lock = threading.Lock()
self.shared_audio_data = None
# vad
self.shared_vad_data = None
self.shared_vad_lock = threading.Lock()
# stt
# event
self.record_event = threading.Event()
self.vad_event = threading.Event()
self.stt_event = threading.Event()
self._debug_count = 0
'''
shared_waiting: 控制所有线程的待机状态,True表示待机,False表示工作
shared_hd_trigger: 控制硬件触发器的状态,True表示触发,False表示未触发
shared_kw_trigger: 控制语音触发器的状态,True表示触发,False表示未触发
share_audio_data: 共享音频数据,用于存储从麦克风采集的音频数据
'''
# create threads
threads = [threading.Thread(target=self.hardware_trigger_thread, args=(recorder,))]
if self.voice_trigger:
vioce_threads = [
threading.Thread(target=self.voice_record_thread, args=(recorder,)),
# threading.Thread(target=self.vad_thread, args=(recorder,)),
threading.Thread(target=self.stt_thread, args=(recorder,)),
]
threads.extend(vioce_threads)
for thread in threads:
thread.start()
# self.logger.info("Audio Process started.")
while True:
'''
# Warning: 一定要加延时!!!否则会有bug!!!
time.sleep(0.001)
if (self.shared_hd_trigger or self.shared_kw_trigger):
# print(f"self.shared_hd_trigger: {self.shared_hd_trigger}, self.shared_kw_trigger: {self.shared_kw_trigger}")
audio_data = self.shared_audio_data
trigger_queue.put(('trgrigger_status', True))
client_queue.put(('audio', audio_data))
self.shared_lock.acquire() # 加锁
self.shared_hd_trigger = False
self.shared_kw_trigger = False
self.shared_audio_data = None
self.shared_waiting = False
self.shared_lock.release() # 释放锁
'''
self.record_event.wait() # 等待record线程被唤醒
trigger_queue.put(('trgrigger_status', True))
client_queue.put(('audio', self.shared_audio_data))
# print(f"send audio data to client"); exit()
def hardware_trigger_thread(self, recorder):
"""hardware_trigger_thread
Args:
recorder: takway.audio_utils.Recorder, recorder object
"""
self.logger.info("Hardware trigger thread started.")
trgrigger_status = False
while True:
time.sleep(0.2)
if self.shared_waiting:
continue
trgrigger_status = recorder.get_hardware_trigger_status()
if trgrigger_status:
self.shared_lock.acquire()
self.shared_waiting = True # shared_waiting 控制所有线程的待机状态,True表示待机,False表示工作
self.shared_hd_trigger = True # share_hd_trigger 控制硬件触发器的状态,True表示触发,False表示未触发
self.shared_lock.release()
# record microphone data
audio_data = recorder.record_hardware()
self.shared_data_lock.acquire()
self.shared_audio_data = audio_data # shared_audio_data 共享音频数据,用于存储从麦克风采集的音频数据
self.shared_data_lock.release()
self.record_event.set() # 唤醒record线程
else:
self.shared_lock.acquire()
self.shared_waiting = False # 释放
self.shared_lock.release()
def voice_record_thread(self, recorder, keywords=['你好']):
"""voice_record_thread
Args:
recorder: takway.audio_utils.Recorder, recorder object
"""
self.logger.info("voice record thread started.")
while True:
if self.shared_waiting:
time.sleep(0.01)
continue
frames = []
# status buffer
is_currently_speaking = False
buffer_size = recorder.vad_buffer_size
# buffer_size = 6
active_buffer = deque([False for i in range(buffer_size-1)]+[True], maxlen=buffer_size)
audio_buffer = deque(maxlen=buffer_size)
silence_buffer = deque([True for i in range(buffer_size)]+[False], maxlen=buffer_size)
while True:
data = recorder.record_chunk_voice(
CHUNK=recorder.vad_chunk_size,
return_type=None,
exception_on_overflow=False)
if data is None:
continue
t1 = time.time()
# print(f"VAD is_speech: {recorder.is_speech(data)}")
# print(f"VAD cost: {(time.time() - t1)/1000} ms")
if recorder.is_speech(data):
# 标志位buffer
active_buffer.append(True); active_buffer.popleft()
silence_buffer.append(False); silence_buffer.popleft()
# 暂时增加到buffer中
audio_buffer.append(data)
# 如果满足检测要求
if all(active_buffer):
if not is_currently_speaking:
print("Speech start detected")
is_currently_speaking = True
frames.extend(audio_buffer) # 把说话的buffer也加上
if is_currently_speaking:
frames.append(data)
else:
# 标志位buffer
# active_buffer.append(False); active_buffer.popleft()
silence_buffer.append(True); silence_buffer.popleft()
if all(silence_buffer):
# 检测到人声并持续录音
if is_currently_speaking:
# 结束标志位
print("Speech end detected")
# print("frames length: ", len(frames))
self.shared_vad_lock.acquire()
self.shared_vad_data = frames
self.shared_vad_lock.release()
self.stt_event.set() # 唤醒stt线程
print("Wake stt thread")
break
else:
frames = []
'''
# print(f"audio_data: {len(audio_data)}")
self.shared_lock.acquire()
self.shared_audio_data = audio_data
self.shared_lock.release()
self.vad_event.set() # 唤醒vad线程
'''
'''
def vad_thread(self, recorder):
self.logger.info("VAD thread started.")
while True:
frames = []
# status buffer
is_currently_speaking = False
buffer_size = recorder.vad_buffer_size
active_buffer = deque([False for i in range(buffer_size)], maxlen=buffer_size)
audio_buffer = deque(maxlen=buffer_size)
silence_buffer = deque([True for i in range(buffer_size)], maxlen=buffer_size)
while True:
self.vad_event.wait() # 等待vad线程被唤醒
data = self.shared_audio_data
if data is None:
continue
t1 = time.time()
print(f"VAD is_speech: {recorder.is_speech(data)}")
print(f"VAD cost: {(time.time() - t1)/1000} ms")
if recorder.is_speech(data):
# 标志位buffer
active_buffer.append(True); active_buffer.popleft()
silence_buffer.append(False); silence_buffer.popleft()
# 暂时增加到buffer中
audio_buffer.append(data)
# 如果满足检测要求
if all(active_buffer):
if not is_currently_speaking:
print("Speech start detected")
is_currently_speaking = True
frames.extend(audio_buffer) # 把说话的buffer也加上
if is_currently_speaking:
frames.append(data)
else:
# 标志位buffer
active_buffer.append(False); active_buffer.popleft()
silence_buffer.append(True); silence_buffer.popleft()
# 检测到人声并持续录音
if is_currently_speaking:
# 结束标志位
if all(silence_buffer):
print("Speech end detected")
# print("frames length: ", len(frames))
self.shared_vad_lock.acquire()
self.shared_vad_data = frames
self.shared_vad_lock.release()
self.stt_event.set() # 唤醒stt线程
break
'''
def stt_thread(self, recorder):
"""stt_thread
Args:
recorder: takway.audio_utils.Recorder, recorder object
"""
self.logger.info("STT thread started.")
from takway.vosk_utils import AutoSpeechRecognizer
asr = AutoSpeechRecognizer(**self.asr_args)
asr.add_keyword(self.keywords)
kw_trgrigger_status = False
while True:
self.stt_event.wait() # 等待stt线程被唤醒
print("STT thread start")
data = self.shared_vad_data
if data is None:
continue
print("Start to Recongnize key words")
kw_trgrigger_status = asr.recognize_keywords(data, partial_size=512)
print("Finish to Recongnize key words")
if kw_trgrigger_status:
self.shared_lock.acquire()
self.shared_kw_trigger = True # share_kw_trigger 语音关键词触发器的状态,True表示触发,False表示未触发
self.shared_lock.release()
self.record_event.set() # 唤醒record线程
kw_trgrigger_status = False
# print(f"Got keyword trigger"); exit()
def camera_process(self, logger, trigger_queue, client_queue):
from takway.cam_utils import Camera
cam = Camera(self.video_args)
while True:
if trigger_queue.empty():
time.sleep(0.5)
else:
item = trigger_queue.get()
if item[0] == 'trgrigger_status' and item[1]:
_, frame = cap.read()
client_queue.put(('image', frame))
def local_client_process(self, logger, client_queue,audio_play_queue,emo_display_queue):
from takway.client_utils import Client
client = Client(**self.server_args)
# print("Local client process started.")
self.logger.info("Local client process started.")
image = None; audio = None
chat_status = 'init'
while True:
if client_queue.empty():
time.sleep(0.2)
else:
item = client_queue.get()
# print(f"Get item: {item[0]}")
if item[0] == 'image':
# TODO: analyise image and send text to server
image = None
if item[0] == 'audio':
audio = item[1]
print("get audio data.")
emo_display_queue.put(('emo_data', 'happy'))
'''
# 发送数据到服务器
response = client.send_data_to_server(
text=None, audio_data=audio, image_data=None, chat_status=chat_status)
print("get response from server.")
chat_status = 'chating'
print(f"response: {response}")
audio_play_queue.put(('audio', response))
'''
image = None; audio = None
def audio_play_process(self, logger, audio_play_queue):
from takway.audio_utils import AudioPlayer
audio_player = AudioPlayer()
self.logger.info("Audio play process started.")
while True:
if audio_play_queue.empty():
time.sleep(0.2)
else:
item = audio_play_queue.get()
if item[0] == 'server_data':
# 播放音频
print("Playing audio...")
server_data = item[1]
audio_player.play(server_data['audio_base64'], audio_type='base64')
def emo_display_process(self, logger, emo_display_queue):
from takway.emo_utils import EmoVideoPlayer
emo_player = EmoVideoPlayer(**self.emo_args)
self.logger.info("Emo display process started.")
# logger.info("Emo display process started.")
# print("Emo display process started.")
while True:
if emo_display_queue.empty():
time.sleep(0.2)
seed = random.randrange(0, 1000)
print(f"seed: {seed}")
if seed < 100:
# emo_player.display_emo_opencv(emo_name='静态', stage='seldom_wink')
emo_player.display_emo_maixsense(emo_name='静态', stage='seldom_wink')
else:
item = emo_display_queue.get()
print(f"Emo display process Get item: {item[0]}")
if item[0] == 'emo_data':
server_data = item[1]
print("Displaying emo...")
# emo_player.display_emo_opencv(emo_name='静态', stage='seldom_wink')
# emo_player.display_emo_opencv(emo_name='静态', stage='quick_wink')
emo_player.display_emo_maixsense(emo_name='静态', stage='seldom_wink')
emo_player.display_emo_maixsense(emo_name='静态', stage='quick_wink')
'''
def display_process(q):
print("Display process started.")
while True:
item = q.get()
if item[0] == 'server_data':
server_data = item[1]
# 显示图像和文本
# print("Displaying image and text:", item[1]['image'], item[1]['text'])
print("Displaying image and text:")
# 这里可以加上实际的显示图像和文本的代码
if item[0] == 'image':
# 显示图像和文本
cv2.imshow('image', item[1])
cv2.waitKey(1)
'''
if __name__ == '__main__':
try:
import gpiod as gpio
model_path="vosk-model-small-cn-0.22"
emo_dir="ResizedEmoji"
except:
model_path=r"G:\WorkSpace\CodeWorkspace\GPT_projects\vits_project\vits-uma-genshin-honkai\vosk-model-small-cn-0.22"
emo_dir=r"G:\WorkSpace\CodeWorkspace\GPT_projects\vits_project\vits-uma-genshin-honkai\ResizedEmoji"
import argparse
parser = argparse.ArgumentParser()
# server params
parser.add_argument('--server_url', type=str, default='http://127.0.0.1:5000/process_all', help='Server url')
# audio paramters
parser.add_argument('--voice_trigger', type=bool, default=True, help='Voice trigger')
parser.add_argument('--record_CHUNK_SIZE', type=int, default=8000, help='Record chunk size')
parser.add_argument('--keywords', type=list, default=['你好'], help='Voice trigger keywords')
# recorder paramters
parser.add_argument('--hd_trigger', type=str, default='keyboard', help='Hardware trigger')
parser.add_argument('--keyboard_key', type=str, default='space', help='Keyboard key')
parser.add_argument('--CHUNK', type=int, default=2048, help='Record chunk size')
parser.add_argument('--RATE', type=int, default=8000, help='Audio rate')
parser.add_argument('--FORMAT', type=int, default=16, help='Audio format')
parser.add_argument('--CHANNELS', type=int, default=1, help='Audio channels')
parser.add_argument('--filename', type=str, default=None, help='Audio file name')
# ASR paramters
# model_path="vosk-model-small-cn-0.22"
# model_path=r"G:\WorkSpace\CodeWorkspace\GPT_projects\vits_project\vits-uma-genshin-honkai\vosk-model-small-cn-0.22"
parser.add_argument('--model_path', type=str, default=model_path, help='Vosk model path')
# video paramters
parser.add_argument('--device', type=str, default='pc', help='Video device')
parser.add_argument('--width', type=int, default=1280, help='Video width')
parser.add_argument('--height', type=int, default=720, help='Video height')
# emo paramters
# emo_dir="ResizedEmoji"
# emo_dir=r"G:\WorkSpace\CodeWorkspace\GPT_projects\vits_project\vits-uma-genshin-honkai\ResizedEmoji"
parser.add_argument('--emo_dir', type=str, default=emo_dir, help='Emo dir')
# log paramters
parser.add_argument('--log_file', type=str, default='my.log', help='Log file')
parser.add_argument('--log_level', type=str, default='INFO', help='Log level')
parser.add_argument('--debug', type=bool, default=True, help='Debug mode')
args = parser.parse_args()
# sort out args and params
server_args = {
'server_url': args.server_url,
}
audio_args = {
'voice_trigger': args.voice_trigger,
'keywords': args.keywords,
'record_CHUNK_SIZE': args.record_CHUNK_SIZE,
}
recorder_args = {
'hd_trigger': args.hd_trigger,
'keyboard_key': args.keyboard_key,
'model_path': args.model_path,
'CHUNK': args.CHUNK,
'FORMAT': pyaudio.paInt16 if args.FORMAT == 16 else pyaudio.paInt32,
'CHANNELS': args.CHANNELS,
'RATE': args.RATE,
'filename': args.filename,
}
asr_args = {
'model_path': args.model_path,
'RATE': args.RATE,
'debug': args.debug,
}
video_args = {
'device': args.device,
'width': args.width,
'height': args.height,
}
emo_args = {
'emo_dir': args.emo_dir,
}
log_args = {
'log_file': args.log_file,
'log_level': args.log_level,
}
web_request_mp_manager = WebRequestMPManager(
server_args=server_args,
audio_args=audio_args,
recorder_args=recorder_args,
asr_args=asr_args,
video_args=video_args,
emo_args=emo_args,
log_args=log_args)
web_request_mp_manager.process_init()