操作定制万年历投屏模拟点单叫号器
目前某些10寸的万年历,电子相册,价格到了100多点,一块屏幕也就这样吧。不论是什么材质的吧,再加50可以支持dlna投屏,还要啥自行车。
我一直在寻找一块可以报号的屏幕和喇叭,就是点餐报号用的,目前成套下来,无线键盘+3位数字的屏幕,也是100上下。
我一般只开1周完成的项目,这次也这样,定时一周,把叫号的内容投屏到电子万年历上。这样不叫号,还能当日历用。现在想来,有空闲了,就叫一个号码,也就是比如餐好了。屏幕就叫 一声,几号餐好。没事的时候,显示默认画面,这就好。
根据AI,ffmeg项目,可以pipen一个管道,python可以生成视频复合音频流。
通过dlna,cast chrome,airplay投送到万年历屏幕。其中dlna应该是兼容最好的。
第一天
2.26先定个目标,生成mpeg的视频流。
2.27
文字转语音是必须的,gtts需要谷歌在线,后来使用pyttsx3
https://blog.csdn.net/cui_yonghua/article/details/134611001
import pyttsx3
pyttsx3.speak("I will speak this text")
import os
import cv2
import time
import subprocess
#import numpy as np
from pyttsx3 import init
from pydub import AudioSegment
from threading import Thread
class ImageRTSPStreamer:
def __init__(self, img_paths, tts_text, fps=25, rtsp_url="rtsp://localhost:8554/mytts"):
self.img_paths = img_paths
self.tts_text = tts_text
self.fps = fps
self.rtsp_url = rtsp_url
self.audio_ready = False
def generate_audio(self):
"""生成语音并转码为PCM WAV格式"""
tts = gTTS(text=self.tts_text, lang='en')
tts.save("temp_audio.mp3")
engine = init()
engine.setProperty('rate', 150) #速度 默认200
engine.setProperty('volume', 0.9)
engine.save_to_file(self.tts_text, 'temp_audio.mp3')
engine.runAndWait()
# 转换为FFmpeg兼容的音频格式
audio = AudioSegment.from_mp3("temp_audio.mp3")
audio = audio.set_frame_rate(44100).set_channels(1)
audio.export("temp_audio.wav", format="wav")
# 转换到原始的PCM_S16LE格式
subprocess.run([
'ffmpeg', '-y',
'-i', 'temp_audio.wav',
'-f', 's16le',
'-acodec', 'pcm_s16le',
'-ar', '44100',
'audio.raw'
])
self.audio_ready = True
os.remove("temp_audio.mp3")
os.remove("temp_audio.wav")
def send_video(self, pipe):
"""发送图片帧到FFmpeg管道"""
frame_delay = 1 / self.fps
idx = 0
while True:
img = cv2.imread(self.img_paths[idx])
img = cv2.resize(img, (1280, 720))
# YUV420P色彩空间转换
yuv = cv2.cvtColor(img, cv2.COLOR_BGR2YUV_I420)
pipe.write(yuv.tobytes())
# 更新图片索引
idx = (idx + 1) % len(self.img_paths)
time.sleep(frame_delay)
def start_stream(self):
# 生成音频
t_audio = Thread(target=self.generate_audio)
t_audio.start()
# 启动FFmpeg合成管道
ffmpeg_cmd = [
'ffmpeg',
'-y',
'-f', 'rawvideo', # 原始视频输入格式
'-vcodec','rawvideo',
'-pix_fmt', 'yuv420p',
'-s', '1280x720', # 分辨率与图片预处理一致
'-r', str(self.fps),
'-i', '-', # 从stdin读取视频
'-f', 's16le', # PCM音频输入格式
'-acodec','pcm_s16le',
'-ar', '44100',
'-ac', '1',
'-i', 'audio.raw', # 原始音频文件
'-c:v', 'libx264', # 视频编码器
'-preset', 'ultrafast',
'-tune', 'zerolatency',
'-pix_fmt', 'yuv420p',
'-g', '50', # GOP大小
'-c:a', 'aac', # 音频编码器
'-b:a', '128k',
'-f', 'rtsp', # 输出格式
'-rtsp_transport', 'tcp',# 使用TCP传输降低丢包
self.rtsp_url
]
# 等待音频就绪
while not self.audio_ready:
time.sleep(0.1)
# 启动FFmpeg进程
proc = subprocess.Popen(
ffmpeg_cmd,
stdin=subprocess.PIPE,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
# 发送视频帧
self.send_video(proc.stdin)
proc.stdin.close()
proc.wait()
if __name__ == "__main__":
img_folder = ["image1.jpg", "image2.jpg"]
text = "请3号就诊!"
streamer = ImageRTSPStreamer(
img_paths=img_folder,
tts_text=text,
fps=5 # 匹配图片切换速度
)
streamer.start_stream()
哎 opencv 需要 cmake,