

import PySimpleGUI as sg
import sys
import json
import os
import requests
import subprocess
import pygame.camera
import pyaudio
import psutil
import time
#当 运行地址 os.getcwd()
__DIR__ = os.getcwd();
# 登入页面
logo = sg.Image(__DIR__+"\\bin\\image\\100.png")
my_text = sg.Text('XXX-直播伴侣',key = '_text_', visible = True, font=('宋体', 12), size=(0, 1), pad=((165, 0), (10, 0)),justification='center')
#账户
member_title = sg.Text('账号:',pad=((110, 0), (35, 0)),font=('宋体', 12))
member_name = sg.InputText('',key='name',pad=((0, 0), (35, 0)), size=(25, 1))
#密码
pwd_title = sg.Text('密码:',pad=((110, 0), (10, 0)),font=('宋体', 12))
pwd_name = sg.InputText('',key='pwd', pad=((0, 0), (10, 0)), size=(25, 1),password_char='*')
# 弹框提示
# sg.SystemTray.notify('Notification Title', 'This is the notification` message')
hello_button = sg.Button(button_text="登入", # 按钮显示文本
tooltip='登入账号', # 鼠标滑到按钮时显示的文本
border_width=0, # 按钮边框
size=(15, 1), # 按钮的长度,高度
auto_size_button=True, # 自否自适应
button_color=('black', 'white'), # 按钮字体颜色, 按钮的背景色
font=('宋体', 12), # 设置字体,大小
bind_return_key=False, # 是否绑定按键
focus=True, # 鼠标是否放置在此按钮上
pad=((175, 0), (20, 0)), # 设置元素的间距 (左,右),(上,下)
# key='START-EXEC', # 元素唯一标示
visible=True)
layout = [
[logo],
[my_text],#提示语句
[member_title,member_name],
[pwd_title,pwd_name],
[hello_button]
]
icon_ = __DIR__+"\\bin\\icon\\favicon.ico"
window = sg.Window('XXX-直播伴侣', layout,grab_anywhere=True,size=(500,340),icon=icon_)
API_URL = 'http://xxxxxxx.top/api/v1';#htt
HEADER_UR = 'lxxxxxx';
headers ={
"Accept":"*/*",
"Accept-Encoding":"gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
"Content-Type": "application/json",
"Host": HEADER_UR,
# "Access-Token":"695s",
# "Origin": "http://pslv4.kvniaudbfiuve12123.xyz",
# "Referer": "http://pslv4.kvniaudbfiuve12123.xyz",
"Content-Type": "application/json"
}
# event
def get_audio_devices():
p = pyaudio.PyAudio()
devices = []
for i in range(p.get_device_count()):
# print(p.get_device_info_by_index(i).get('name'))
devices.append(p.get_device_info_by_index(i))
return devices
def get_audio_input_devices():
devices = []
for item in get_audio_devices():
if item.get('maxInputChannels') > 0:
devices.append(item)
return devices
def kill_process(pid):
parent_proc = psutil.Process(pid)
for child_proc in parent_proc.children(recursive=True):
child_proc.kill()
parent_proc.kill()
#获取音频设备
Audio_List =[];
# Audio_ =pyaudio.PyAudio()
# print(Audio_.get_default_output_device_info())
# for Audio_id in get_audio_input_devices():
# Audio_List.append(Audio_id.get('name'))
# print(Audio_List) -hide_banner -list_devices true -f dshow -i 0
cmd = __DIR__+'\\bin\\ffmpeg -list_devices true -f dshow -i dummy'#['ffmpeg', '-list_devices','true', '-f','dshow','-i','dummy']
process = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding="utf-8",text=True)
record = False
num_line = 0;
for line in process.stdout:
# print(',,,,,', num_line)
# print(line)
if record:
if line.startswith("[dshow"):
_line = line[index + 2:]
if _line.startswith("DirectShow audio"):
record = False
if record and num_line%2 == 0:
Audio_List.append(_line[2:len(_line)-2])
num_line+=1
if line.startswith("[dshow"):
index = line.find("]");
if index > 0:
_line = line[index+2:]
if _line.startswith("DirectShow audio"):
# print('>>>>>>>', _line)
num_line = 0
record = True
while True:
event, value = window.read()
if event == sg.WIN_CLOSED: break
if event == '登入':
if value['name']=='':
my_text.update(' 账号不能为空') #修改标题
if value['pwd']=='':
my_text.update(' 密码不能为空') #修改标题
#如果都存在进行APP接口登入
data ={
"username":value['name'],
"password":value['pwd'],
"group":"pc"
}
try:
print(API_URL + '/site/login.json')
mediaGet =requests.post(API_URL + '/site/login.json', json.dumps(data), headers = headers, timeout = 5)
# print(mediaGet)
mediaGet = mediaGet.json()
except Exception as e:
#错误提示
print(e)
sg.popup_error('网络异常, 请稍后重试!',icon=icon_)
continue
if mediaGet['code']!=200:
print(mediaGet['message'])
my_text.update(mediaGet['message']) #修改标题
continue;
if mediaGet['code']==200:
sg.SystemTray.notify('登入成功..', '欢迎用户:'+mediaGet['data']['member']['nickname'])
# # print(1)
window.close()
#获取目前已经存在的分类
values = []
cate =requests.get(API_URL + '/live/all-cate.json', headers = headers, timeout = 30)
for cate_ in cate.json()['data']['list']:
values.append(cate_['name'])
#获取直媒体设备
pygame.camera.init()
shexiangtou=pygame.camera.list_cameras()
# print(camera_id_list)
#开启新的页面
layout = [
[sg.Text('直播类型:',pad=((0, 0), (0, 0)),font=('宋体', 12)),sg.Listbox(values=values,key='list',size=(30,7))],
[sg.Text('视频设备:',pad=((0, 0), (0, 0)),font=('宋体', 12)),sg.Listbox(values=shexiangtou,key='video',size=(30,2))],
[sg.Text('音频设备:',pad=((0, 0), (0, 0)),font=('宋体', 12)),sg.Listbox(values=Audio_List,key='audio',size=(30,2))],
[sg.Text('开播标题:',pad=((0, 0), (0, 0)),font=('宋体', 12)),sg.InputText('',key='title',size=(80, 1))],
[sg.Button(button_text="开始直播", # 按钮显示文本
tooltip='开始直播', # 鼠标滑到按钮时显示的文本
border_width=0, # 按钮边框
size=(15, 1), # 按钮的长度,高度
auto_size_button=True, # 自否自适应
button_color=('black', 'white'), # 按钮字体颜色, 按钮的背景色
font=('宋体', 12), # 设置字体,大小
bind_return_key=False, # 是否绑定按键
focus=True, # 鼠标是否放置在此按钮上
pad=((85, 0), (20, 0)), # 设置元素的间距 (左,右),(上,下)
# key='START-EXEC', # 元素唯一标示
visible=True
)]
]
liveOpen = sg.Window('开始直播', layout,grab_anywhere=True,size=(300,380),icon=icon_)
# sg.SystemTray.notify('登入成功..', '欢迎用户:'+mediaGet['data']['member']['nickname'])
event, value = liveOpen.read()
while True:
event, value = liveOpen.read()
if event == sg.WIN_CLOSED: break
if event == '开始直播':
#进行开始直播
#检测未选 进行提示
if value['list'] == []:
sg.popup_error('请选择直播类型!',icon=icon_)
continue;
if value['title'] == '':
sg.popup_error('请输入开播标题!',icon=icon_)
continue;
# video
if value['video'] == []:
sg.popup_error('请选择设备!',icon=icon_)
continue;
if value['audio'] == []:
sg.popup_error('请选择设备!',icon=icon_)
continue;
vate_id = '';
for cate_ in cate.json()['data']['list']:
if value['list'][0] ==cate_['name']:
vate_id =cate_['id']
#执行查询音频命令
# audio_ok = subprocess.run('',encoding="utf-8" , shell=True)
#检测是否存在 不存在提示
if vate_id!="":
#开始请求直播接口
data={
"cate_id":vate_id,
"title":value['title']
}
headers['x-api-key'] = mediaGet['data']['access_token'];
live =requests.post(API_URL + '/live/start-live.json', json.dumps(data), headers = headers, timeout = 30)
live =live.json()
if live['code']!=200:
sg.popup_error(live['message'])
continue;
#进行推流直播 ffmpeg -f dshow -i video="USB2.0 PC CAMERA" -f dshow -i audio="麦克风 (2- USB2.0 MIC)" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f flv rtmp://127.0.0.1:1935/live/123
cmd_rtmp = __DIR__+'\\bin\\ffmpeg -f dshow -i video="'+value['video'][0]+'" -f dshow -i audio="'+value['audio'][0]+'" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f flv "' + live['data']['detail']['video']+'" -loglevel quiet ';
cmd_lx = subprocess.Popen(cmd_rtmp,encoding="utf-8" , shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
# sg.SystemTray.notify('开播成功', '下播请关闭摄像头窗口..')
# print(live['data']['detail']['video'])
print(cmd_rtmp)
liveOpen.disappear() # 窗口隐藏
sg.popup('开播成功!下播请关闭摄像头窗口然后等待提示! 请点击ok继续',icon=icon_)
time.sleep(10)
# cmd_play = __DIR__+'\\bin\\ffplay -f dshow -i video="'+value['video'][0]+'" -loglevel quiet ';
cmd_play = __DIR__+'\\bin\\ffplay ' + live['data']['detail']['video'];
print(cmd_play)
subprocess.run(cmd_play,encoding="utf-8" , shell=True)
print(cmd_lx.pid)
kill_process(cmd_lx.pid)
cmd_lx.kill()
# subprocess.Popen.kill(proc1)
# cmd_lx.terminate()
# Popen.wait()
#如果退出运行- 直接进行下播
live_id = live['data']['detail']['id']
data = {
"live_id":live_id
}
live =requests.post(API_URL + '/live/live-off.json', json.dumps(data), headers = headers, timeout = 30)
liveOpen.reappear() #展示窗口
sg.popup('下播成功!',icon=icon_)
print(live.json())
# ffplay -f dshow -i video="USB2.0 PC CAMERA"
#调用ffmpeg进行直播推流data
# cmd_str =__DIR__+f'\\\bin\\ffmpeg -hide_banner -list_devices true -f dshow -i 0 -loglevel quiet '
# cmd =subprocess.run(cmd_str, encoding="utf-8" , shell=True)
# print(cmd)
#进行直播接口请求
#
# print(mediaGet.json())
# sg.popup_ok('66')
# sg.SystemTray.notify('Notification Title', 'This is the notification` message')
#进行检测提示账户密码不能为空
if event == 'Clean':
my_text.update('')
# window.close()
打包程序
pyinstaller -i "C:/Users/DELL/Desktop/live-exe/bin/icon/favicon.ico" index.py --distpath "C:/Users/DELL/Desktop/live-exe/" --noconsole --clean