本帖最后由 云天 于 2024-1-22 20:19 编辑  
 
行空直播 弹幕物控  
【项目背景】 
       本项目想实现从万物互联到万物可视。通过实景智能直播将智能技术与直播相结合实现新型直播方式,通过实时采集、编辑和传输实景数据,实现更加真实、生动的直播效果。并可通过弹幕留言来实现远程控制浇水、喂食等功能。  【项目设计】 
       平时,会全家出远门,一走好几天。家里的花和猫都处于无人照顾的情况。有时会给花一次性浇很多水,给猫放很多的猫粮和水。花还好,就是猫,每次回来都会胖很多。 
       想通过网络查看家里的情况,并能通过远程控制的方式,给花浇水、给猫喂食。远程控制可以使用物联网,查看图像可使用网络摄像头。那怎么将两者结合,我想到了直播。 
【项目方案】 
       1.使用B站直播,获取服务器地址和直播码。2.使用opencv库获取摄像头图像,使用FFmpeg进程,将视频数据通过管道传递给RTMP推流B站,进行直播。 
       3.通过Pinpong库获取温湿度传感器、土壤湿度传感器数值,并通过“ImageDraw”库将中文及传感器数值绘制在画面上。 
       4.使用浏览器“开发者工具”,获取cookies和headers。 
       5.通过requests库的get方法,获取直播弹幕留言,并通过pinpong库控制舵机及电磁继电器。 
【硬件装置】 
       行空板加扩展板,温湿度传感器接P1引脚,土壤湿度传感器接P4引脚,光照传感器接P10引脚。两舵机分别引脚P8、P9。电磁继电器和蓝光LED分别接P20、P19引脚。 
 
       土壤湿度传感器插入花盆土壤中。 
 
       水泵出水口有夹子固定到花盆里。 
 
       水泵电源接电磁继电器 
 
       摄像头接行空板USB口,并固定在直播架上。 
 
 
 
 
 
【获取直播推流码】 
 
 
 
【直播推流】 
行空板自带了ffmpeg库,可直接使用。 
			
			
			- import cv2
 - 
 - import subprocess
 - 
 - # 设置摄像头参数
 - capture = cv2.VideoCapture(0)
 - capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
 - capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
 - 
 - # RTMP推流地址
 - url = 'rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_511218715_31018533&key=*****************&schedule=rtmp&pflag=1'
 - 
 - # 启动FFmpeg进程,将视频数据通过管道传递给RTMP推流
 - cmd = ['ffmpeg', '-y', '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-s', '640x480', '-i', '-', '-c:v', 'libx264', '-pix_fmt', \
 -    'yuv420p', '-preset', 'ultrafast', '-f', 'flv', url]
 - p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
 - 
 - # 循环读取摄像头数据,将数据写入管道中
 - while True:
 -     ret, frame = capture.read()
 -     if not ret:
 -       break
 - 
 -     p.stdin.write(frame.tostring())
 - 
 - # 关闭进程和摄像头
 - p.communicate()
 - p.stdin.close()
 - capture.release()
 
  复制代码
  
 
【实时数据显示】 
通过Pinpong库获取温湿度传感器、土壤湿度传感器数值,并通过“ImageDraw”库将中文及传感器数值绘制在画面上。 
 
- 
 - import cv2
 - 
 - import subprocess
 - from PIL import ImageFont,ImageDraw,Image
 - import numpy as np
 - from pinpong.board import DHT11
 - from pinpong.board import Board
 - from pinpong.board import Pin
 - 
 - 
 - Board().begin()
 - pin1 = Pin(Pin.P1)
 - dht1 = DHT11(pin1)
 - pin0 = Pin(Pin.P4, Pin.ANALOG)
 - pin2 = Pin(Pin.P2, Pin.ANALOG)
 - # 设置摄像头参数
 - capture = cv2.VideoCapture(0)
 - capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
 - capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
 - 
 - # RTMP推流地址
 - url = 'rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_511218715_31018533&key=*********************&schedule=rtmp&pflag=1'
 - 
 - # 启动FFmpeg进程,将视频数据通过管道传递给RTMP推流
 - cmd = ['ffmpeg', '-y', '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-s', '640x480', '-i', '-', '-c:v', 'libx264', '-pix_fmt', \
 -   'yuv420p', '-preset', 'ultrafast', '-f', 'flv', url]
 - p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
 - 
 - # 循环读取摄像头数据,将数据写入管道中
 - while True:
 -   ret, frame = capture.read()
 -   if not ret:
 -       break
 -   #cv2.putText(frame, "hello", (100, 100), cv2.FONT_HERSHEY_COMPLEX, 1,(255,0,0),1)
 -   frame=Image.fromarray(frame)
 -   font1=ImageFont.truetype("./msyh.ttc",50)
 -   draw=ImageDraw.Draw(frame)
 -   draw.text((10,10),"温度:"+str(dht1.temp_c())+"  湿度:"+str(dht1.humidity()),font=font1,fill=(0,0,255))
 -   draw.text((10,400),"光照:"+str(pin2.read_analog())+"  土湿度:"+str(pin0.read_analog()),font=font1,fill=(0,0,255))
 -   frame=np.array(frame)
 -   p.stdin.write(frame.tostring())
 - 
 - # 关闭进程和摄像头
 - p.communicate()
 - p.stdin.close()
 - capture.release()
 
  复制代码
  
【获取直播信息】 
 
       使用浏览器“开发者工具”,获取cookies和headers。 
       1.复制信息 
 
       2.使用Convert curl commands to Python (curlconverter.com)网站工具,将信息转换为python可用数据。 
 
(cookies信息有效期为7天)  
 
【弹幕控制】 
        通过requests库的get方法,获取直播弹幕留言。 
- 
 - import requests
 - import time
 - import random
 - import json
 - 
 - 
 - def send_Danmu():
 -     watertime=""
 -     liketime=""
 -     watertimetem=""
 -     liketimetem=""
 -     while True:
 -  
 -        cookies = {**************}
 - 
 -        headers = {**************}
 - 
 -         response = requests.get('https://api.live.bilibili.com/xlive/web-room/v1/dM/gethistory?roomid=23994618&room_type=0', cookies=cookies, headers=headers)
 -         json_data=response.text
 -         
 -         data=json.loads(json_data)
 -         if data["code"]==0:
 -              texts=data["data"]["room"]
 -              for text in texts :
 -                  if text["nickname"]=="创客云天":
 -                    if text["text"]=="浇水":
 -                        if text["timeline"]!=watertimetem:
 -                            watertimetem=text["timeline"]
 -                            
 -                  if text["text"]=="[牛]": 
 -                      if text["timeline"]!=liketimetem:
 -                          liketimetem= text["timeline"]
 -                          
 -              if watertimetem!=watertime:
 -                 watertime=watertimetem
 -                 print("浇水")
 -              if liketimetem!=liketime:
 -                 liketime=liketimetem
 -                 print("[牛]")
 -         time. sleep(21)#冷却时间,可以自己调
 - send_Danmu()
 
  复制代码       并通过pinpong库控制舵机及电磁继电器。- 
 - from pinpong.board import Board
 - from pinpong.board import Pin
 - import requests
 - import time
 - import random
 - import json
 - Board().begin()
 - pin20 = Pin(Pin.P20, Pin.OUT)
 - pin19 = Pin(Pin.P19, Pin.OUT)
 - def send_Danmu():
 - 
 -     watertime=""
 -     liketime=""
 -     watertimetem=""
 -     liketimetem=""
 -     bs=0
 -     timekg=time.time()
 -     timefw=time.time()
 -     while True:
 -       if time.time()-timefw>5:
 -         timefw=time.time()
 -         cookies = {**************}
 - 
 -         headers = {**************}
 - 
 -         response = requests.get('https://api.live.bilibili.com/xlive/web-room/v1/dM/gethistory?roomid=23994618&room_type=0', cookies=cookies, headers=headers)
 -         json_data=response.text
 -         
 -         data=json.loads(json_data)
 -         if data["code"]==0:
 -              texts=data["data"]["room"]
 -              for text in texts :
 -                  if text["nickname"]=="创客云天":
 -                    if text["text"]=="浇水":
 -                        if text["timeline"]!=watertimetem:
 -                            watertimetem=text["timeline"]
 -                            
 -                  if text["text"]=="[牛]": 
 -                      if text["timeline"]!=liketimetem:
 -                          liketimetem= text["timeline"]
 -                          
 -              if watertimetem!=watertime:
 -                  if bs==0:
 -                    watertime=watertimetem
 -                    pin20.value(1)
 -                    pin19.value(1)                
 -                    timekg=time.time()
 -                    bs=1
 -                    print("开始浇水 ")
 -              if liketimetem!=liketime:
 -                 liketime=liketimetem
 -                 print("[牛]")
 -       if time.time()-timekg>3:
 -            if bs==1:
 -              timekg=time.time()  
 -              pin20.value(0)
 -              pin19.value(0)
 -              bs=0
 -              print("停止浇水 ")       
 -       
 - send_Danmu()
 
  复制代码       增加控制舵机功能- 
 - from pinpong.board import Board,Servo
 - from pinpong.board import Pin
 - import requests
 - import time
 - import random
 - import json
 - Board().begin()
 - pin20 = Pin(Pin.P20, Pin.OUT)
 - pin19 = Pin(Pin.P19, Pin.OUT)
 - pin20.value(0)
 - pin19.value(0)
 - s1 = Servo(Pin(Pin.P8))
 - s2 = Servo(Pin(Pin.P9))
 - def send_Danmu():
 - 
 -     watertime=""
 -     liketime=""
 -     watertimetem=""
 -     liketimetem=""
 -     bs=0
 -     bs2=0
 -     timekg=time.time()
 -     timefw=time.time()
 -     timedj=time.time()
 -     while True:
 -       if time.time()-timefw>5:
 -         timefw=time.time()
 -         cookies = {******************}
 - 
 -         headers = {******************}
 - 
 -         response = requests.get('https://api.live.bilibili.com/xlive/web-room/v1/dM/gethistory?roomid=23994618&room_type=0', cookies=cookies, headers=headers)
 -         json_data=response.text
 -         
 -         data=json.loads(json_data)
 -         if data["code"]==0:
 -              texts=data["data"]["room"]
 -              for text in texts :
 -                  if text["nickname"]=="创客云天":
 -                    if text["text"]=="浇水":
 -                        if text["timeline"]!=watertimetem:
 -                            watertimetem=text["timeline"]
 -                            
 -                  if text["text"]=="[牛]": 
 -                      if text["timeline"]!=liketimetem:
 -                          liketimetem= text["timeline"]
 -                          
 -              if watertimetem!=watertime:
 -                  if bs==0:
 -                    watertime=watertimetem
 -                    pin20.value(1)
 -                    pin19.value(1)                
 -                    timekg=time.time()
 -                    bs=1
 -                    print("开始浇水 ")
 -              if liketimetem!=liketime:
 -                 liketime=liketimetem
 -                 s1.angle(60) #控制舵机转到0度位置
 -                 s2.angle(60) #控制舵机转到0度位置
 -                 timedj=time.time()
 -                 bs2=1
 -                 print("开始摆动")
 -       if time.time()-timekg>3:
 -            if bs==1:
 -              timekg=time.time()  
 -              pin20.value(0)
 -              pin19.value(0)
 -              bs=0
 -              print("停止浇水 ")
 -       if time.time()-timedj>3:
 -            if bs2==1:
 -              timedj=time.time()  
 -              s1.angle(120) #控制舵机转到0度位置
 -              s2.angle(120) #控制舵机转到0度位置
 -              bs2=0
 -              print("停止摆动")              
 -       
 - send_Danmu()
 
  复制代码 【完整代码】 
将直播与弹幕控制程序结合- 
 - import cv2
 - 
 - import subprocess
 - from PIL import ImageFont,ImageDraw,Image
 - import numpy as np
 - from pinpong.board import DHT11
 - from pinpong.board import Board,Servo
 - from pinpong.board import Pin
 - import requests
 - import time
 - import random
 - import json
 - from unihiker import GUI
 - u_gui=GUI()
 - 显示1=u_gui.draw_text(text="行空板",x=30,y=10,font_size=40, color="#0000FF")
 - 显示2=u_gui.draw_text(text="直播控制",x=10,y=80,font_size=40, color="#FF0000")
 - 显示3=u_gui.draw_text(text="",x=10,y=180,font_size=40, color="#00FF00")
 - 
 - Board().begin()
 - pin20 = Pin(Pin.P20, Pin.OUT)
 - pin19 = Pin(Pin.P19, Pin.OUT)
 - pin20.value(0)
 - pin19.value(0)
 - s1 = Servo(Pin(Pin.P8))
 - s2 = Servo(Pin(Pin.P9))
 - pin1 = Pin(Pin.P1)
 - dht1 = DHT11(pin1)
 - pin4 = Pin(Pin.P4, Pin.ANALOG)
 - pin10 = Pin(Pin.P10, Pin.ANALOG)
 - 
 - watertime=""
 - liketime=""
 - watertimetem=""
 - liketimetem=""
 - bs=0
 - bs2=0
 - timekg=time.time()
 - timefw=time.time()
 - timedj=time.time()
 - 
 - # 设置摄像头参数
 - capture = cv2.VideoCapture(0)
 - capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
 - capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
 - 
 - # RTMP推流地址
 - url = 'rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_511218715_31018533&key=**************************&schedule=rtmp&pflag=1'
 - 
 - # 启动FFmpeg进程,将视频数据通过管道传递给RTMP推流
 - cmd = ['ffmpeg', '-y', '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-s', '640x480', '-i', '-', '-c:v', 'libx264', '-pix_fmt', \
 -    'yuv420p', '-preset', 'ultrafast', '-f', 'flv', url]
 - p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
 - 
 - # 循环读取摄像头数据,将数据写入管道中
 - while True:
 -    ret, frame = capture.read()
 -    if not ret:
 -        break
 -    #cv2.putText(frame, "hello", (100, 100), cv2.FONT_HERSHEY_COMPLEX, 1,(255,0,0),1) 
 -    frame=Image.fromarray(frame)
 -    font1=ImageFont.truetype("./msyh.ttc",50)
 -    draw=ImageDraw.Draw(frame)
 -    draw.text((10,10),"温度:"+str(dht1.temp_c())+"  湿度:"+str(dht1.humidity()),font=font1,fill=(0,0,255))
 -    draw.text((10,400),"光照:"+str(pin10.read_analog())+"  土湿度:"+str(pin4.read_analog()),font=font1,fill=(0,0,255))
 -    frame=np.array(frame)
 -    p.stdin.write(frame.tostring())
 -    if time.time()-timefw>5:
 -         timefw=time.time()
 -         cookies = {***********************************}
 - 
 -         headers = {***********************************}
 - 
 -         response = requests.get('https://api.live.bilibili.com/xlive/web-room/v1/dM/gethistory?roomid=23994618&room_type=0', cookies=cookies, headers=headers)
 -         json_data=response.text
 -         
 -         data=json.loads(json_data)
 -         if data["code"]==0:
 -              texts=data["data"]["room"]
 -              for text in texts :
 -                  if text["nickname"]=="创客云天":
 -                    if text["text"]=="浇水":
 -                        if text["timeline"]!=watertimetem:
 -                            watertimetem=text["timeline"]
 -                            显示3.config(text=text["nickname"])
 -                  if text["text"]=="[牛]": 
 -                      if text["timeline"]!=liketimetem:
 -                          liketimetem= text["timeline"]
 -                          显示3.config(text=text["nickname"])
 -                          
 -              if watertimetem!=watertime:
 -                  if bs==0:
 -                    watertime=watertimetem
 -                    pin20.value(1)
 -                    pin19.value(1)                
 -                    timekg=time.time()
 -                    bs=1
 -                    print("开始浇水 ")
 -              if liketimetem!=liketime:
 -                 liketime=liketimetem
 -                 s1.angle(60) #控制舵机转到0度位置
 -                 s2.angle(120) #控制舵机转到0度位置
 -                 pin20.value(1)
 -                 timedj=time.time()
 -                 bs2=1
 -                 print("开始摆动")
 -    if time.time()-timekg>3:
 -            if bs==1:
 -              timekg=time.time()  
 -              pin20.value(0)
 -              pin19.value(0)
 -              bs=0
 -              print("停止浇水 ")
 -    if time.time()-timedj>3:
 -            if bs2==1:
 -              timedj=time.time()  
 -              s1.angle(120) #控制舵机转到0度位置
 -              s2.angle(60) #控制舵机转到0度位置
 -              pin20.value(0)
 -              bs2=0
 -              print("停止摆动")  
 - # 关闭进程和摄像头
 - p.communicate()
 - p.stdin.close()
 - capture.release()
 
  复制代码
  
  
 
  
 
【演示视频】  
 
 
 
 
 
 |