如何解决检查不同节点不同 IP 地址、同一网络上的文件 - 可能吗?
我有一小部分 RaspBerry Pi,都在同一个本地网络 (192.168.1.2xx) 上,都在运行 Python 3.7.3,一个 (R Pi CM3) 在 Raspbian Buster 上,另一个 (R Pi 4B 8gig)在 RaspBerry Pi OS 64 上。
我在一台设备(Pi 4B)上有一个文件,位于 /tmp/speech.wav,它是实时生成的:
192.168.1.201 - /tmp/speech.wav
我有一个在该设备上运行良好的脚本,它告诉我 .wav 文件的播放持续时间(以秒为单位):
import wave
import contextlib
def getPlayTime():
fname = '/tmp/speech.wav'
with contextlib.closing(wave.open(fname,'r')) as f:
frames = f.getnframes()
rate = f.getframerate()
duration = round(frames / float(rate),2)
return duration
但是 - 需要对该持续时间信息进行操作的节点正在 192.168.1.210 的另一个节点上运行。我不能简单地将各种文件全部移动到同一个节点,因为有很多事情发生,事情是有原因的。
所以我需要知道的是如何改变我的方法,以便我可以将脚本引用更改为类似以下伪代码的内容:
fname = '/tmp/speech.wav @ 192.168.1.201'
这样的事情可能吗?在网上搜索,我似乎遇到了数百万人在寻找如何获取 IP 地址、修复多个 IP 地址问题、修复重复 IP 地址问题……但我似乎还没有找到如何简单地检查文件正如我在此处描述的那样,在不同的 IP 地址上。我没有网络安全限制,所以任何设置都需要考虑。非常感谢您的帮助。
解决方法
有很多可能性,这可能归结为您需要多久检查一次持续时间、从多少个客户端、文件更改的频率以及您是否有其他信息要在节点之间共享。
这里有一些选项:
-
在具有 WAV 文件的 Pi 上设置一个 SMB(Samba)服务器,并让其他节点挂载文件系统并像访问本地文件一样访问该文件
-
在具有 WAV 文件的 Pi 上设置 NFS 服务器,让其他节点挂载文件系统并像访问本地文件一样访问该文件
-
让其他节点使用
ssh
登录并提取持续时间,或使用scp
检索文件 - 参见 Python 中的 paramiko -
在一个节点上设置 Redis 并将 WAV 文件放在那里,以便任何人都可以获取它 - 如果您有很多列表、数组、字符串、整数、哈希,这可能很有吸引力,要在 Raspberry Pi 之间快速共享的队列或集合。示例 here。
这是一个非常简单的示例,它从一个节点(假设 Redis 在 192.168.0.200)将音轨写入 Redis,然后从任何其他节点读回。当然,您可能只希望写入节点在其中写入持续时间而不是整个轨道 - 这会更有效率。或者,您可能想要存储大量其他共享数据或设置。
这是作者:
#!/usr/bin/env python3
import redis
from pathlib import Path
host='192.168.1.200'
# Connect to Redis
r = redis.Redis(host)
# Load some music,or otherwise create it
music = Path('song.wav').read_bytes()
# Put music into Redis where others can see it
r.set("music",music)
这是读者:
#!/usr/bin/env python3
import redis
from pathlib import Path
host='192.168.1.200'
# Connect to Redis
r = redis.Redis(host)
# Retrieve music track from Redis
music = r.get("music")
print(f'{len(music)} bytes read from Redis')
然后,在测试期间,您可能希望从终端手动将轨道推送到 Redis:
redis-cli -x -h 192.168.0.200 set music < OtherTrack.wav
或者手动从 Redis 检索轨道到文件:
redis-cli -h 192.168.0.200 get music > RetrievedFromRedis.wav
,
好的,这就是我最终确定的 - 并且效果很好。使用 ZeroMQ 进行消息传递,我有获取 wav 播放时间的功能,另一个收集有关将要说的语音的数据,然后在发送语音之前将所有数据发送到电机核心。运动核心处理时间问题,使下巴与语音同步。所以,我实际上并没有将生成 wav 的代码并将 wav 播放时间的长度返回到最终使用它的节点上,但事实证明消息传递足够快,所以有足够的时间空间来接收、处理和实施运动控制以完美匹配语音。将其发布在这里,以防它对将来处理类似问题的人们有所帮助。
import time
import zmq
import os
import re
import wave
import contextlib
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5555") #Listens for speech to output
print("Connecting to Motor Control")
jawCmd = context.socket(zmq.PUB)
jawCmd.connect("tcp://192.168.1.210:5554") #Sends to MotorFunctions for Jaw Movement
def getPlayTime(): # Checks to see if current file duration has changed
fname = '/tmp/speech.wav' # and if yes,sends new duration
with contextlib.closing(wave.open(fname,'r')) as f:
frames = f.getnframes()
rate = f.getframerate()
duration = round(frames / float(rate),3)
speakTime = str(duration)
return speakTime
def set_voice(V,T):
T2 = '"' + T + '"'
audioFile = "/tmp/speech.wav" # /tmp set as tmpfs,or RAMDISK to reduce SD Card write ops
if V == "A":
voice = "Allison"
elif V == "B":
voice = "Belle"
elif V == "C":
voice = "Callie"
elif V == "D":
voice = "Dallas"
elif V == "V":
voice = "David"
else:
voice = "Belle"
os.system("swift -n " + voice + " -o " + audioFile + " " +T2) # Record audio
tailTrim = .5 # Calculate Jaw Timing
speakTime = eval(getPlayTime()) # Start by getting playlength
speakTime = round((speakTime - tailTrim),2) # Chop .5 s for trailing silence
wordList = T.split()
jawString = []
for index in range(len(wordList)):
wordLen = len(wordList[index])
jawString.append(wordLen)
jawString = str(jawString)
speakTime = str(speakTime)
jawString = speakTime + "|" + jawString # 3.456|[4,2,7,4,9,3,6] - will split on "|"
jawCmd.send_string(jawString) # Send Jaw Operating Sequence
os.system("aplay " + audioFile) # Play audio
pronunciationDict = {'teh':'the','process':'prawcess','Maeve':'Mayve','Mariposa':'May-reeposah','Lila':'Lala','Trump':'Ass hole'}
def adjustResponse(response): # Adjusts spellings in output string to create better speech output.
for key,value in pronunciationDict.items():
if key in response or key.lower() in response:
response = re.sub(key,value,response,flags=re.I)
return response
SpeakText="Speech center connected and online."
set_voice(V,SpeakText) # Cepstral Voices: A = Allison; B = Belle; C = Callie; D = Dallas; V = David;
while True:
SpeakText = socket.recv().decode('utf-8') # .decode gets rid of the b' in front of the string
SpeakTextX = adjustResponse(SpeakText) # Run the string through the pronunciation dictionary
print("SpeakText = ",SpeakTextX)
set_voice(V,SpeakTextX)
print("Received request: %s" % SpeakTextX)
socket.send_string(str(SpeakTextX)) # Send data back to source for confirmation
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。