页面及逻辑修改

This commit is contained in:
Jerry Yan 2019-04-08 11:32:05 +08:00
parent 99d148666e
commit c3a965f284
7 changed files with 225 additions and 19 deletions

View File

@ -15,6 +15,7 @@ def reloadConfig():
config = json.load(_config_fp) config = json.load(_config_fp)
_config_fp.close() _config_fp.close()
dt_format="%Y/%m/%d %H:%M:%S" dt_format="%Y/%m/%d %H:%M:%S"
broadcaster = "" broadcaster = ""
@ -23,6 +24,7 @@ isBroadcasting = False
updateTime = "" updateTime = ""
forceStopDownload = False forceStopDownload = False
forceNotBroadcasting = False
uploadQueue = queue.Queue() uploadQueue = queue.Queue()
encodeQueue = queue.Queue() encodeQueue = queue.Queue()
@ -33,6 +35,18 @@ encodeStatus = []
errors = [] errors = []
def parseSize(size):
K = size/1024.0
if K > 1000:
M = K/1024.0
if M > 1000:
return "{:.2f}GB".format(M / 1024.0)
else:
return "{:.2f}MB".format(M)
else:
return "{:.2f}MB".format(K)
def appendUploadStatus(obj): def appendUploadStatus(obj):
global uploadStatus global uploadStatus
if isinstance(obj, dict): if isinstance(obj, dict):
@ -44,7 +58,7 @@ def appendUploadStatus(obj):
"datetime": datetime.strftime(datetime.now(), dt_format), "datetime": datetime.strftime(datetime.now(), dt_format),
"message": str(obj) "message": str(obj)
}) })
uploadStatus = uploadStatus[-10:] uploadStatus = uploadStatus[-config["l_c"]:]
def modifyLastUploadStatus(obj): def modifyLastUploadStatus(obj):
@ -69,7 +83,7 @@ def appendEncodeStatus(obj):
"datetime": datetime.strftime(datetime.now(), dt_format), "datetime": datetime.strftime(datetime.now(), dt_format),
"message": str(obj) "message": str(obj)
}) })
encodeStatus = encodeStatus[-10:] encodeStatus = encodeStatus[-config["l_c"]:]
def modifyLastEncodeStatus(obj): def modifyLastEncodeStatus(obj):
@ -94,7 +108,7 @@ def appendDownloadStatus(obj):
"datetime": datetime.strftime(datetime.now(), dt_format), "datetime": datetime.strftime(datetime.now(), dt_format),
"message": str(obj) "message": str(obj)
}) })
downloadStatus = downloadStatus[-10:] downloadStatus = downloadStatus[-config["l_c"]:]
def modifyLastDownloadStatus(obj): def modifyLastDownloadStatus(obj):
@ -119,7 +133,7 @@ def appendError(obj):
"datetime": datetime.strftime(datetime.now(), dt_format), "datetime": datetime.strftime(datetime.now(), dt_format),
"message": str(obj) "message": str(obj)
}) })
errors = errors[-10:] errors = errors[-config["elc"]:]
class downloader(XiGuaLiveApi): class downloader(XiGuaLiveApi):
@ -127,7 +141,7 @@ class downloader(XiGuaLiveApi):
playlist = None playlist = None
def updRoomInfo(self): def updRoomInfo(self):
global broadcaster, isBroadcasting, updateTime global broadcaster, isBroadcasting, updateTime, forceNotBroadcasting, forceStopDownload
super(downloader, self).updRoomInfo() super(downloader, self).updRoomInfo()
updateTime = datetime.strftime(datetime.now(), dt_format) updateTime = datetime.strftime(datetime.now(), dt_format)
broadcaster = self.roomLiver broadcaster = self.roomLiver
@ -135,6 +149,9 @@ class downloader(XiGuaLiveApi):
if self.isLive: if self.isLive:
self.updPlayList() self.updPlayList()
else: else:
forceStopDownload = False
forceNotBroadcasting = False
self.playlist = False
self.files = [] self.files = []
def updPlayList(self): def updPlayList(self):

View File

@ -1,6 +1,8 @@
import os
from glob import glob
from time import sleep from time import sleep
from flask_cors import CORS from flask_cors import CORS
from flask import Flask, jsonify, request, redirect, url_for from flask import Flask, jsonify, request, redirect, render_template, Response
import Common import Common
import threading import threading
from liveDownloader import run as RUN from liveDownloader import run as RUN
@ -58,19 +60,25 @@ def getAllStats():
return jsonify({"message":"ok","code":200,"status":0,"data":{ return jsonify({"message":"ok","code":200,"status":0,"data":{
"download":Common.downloadStatus, "download":Common.downloadStatus,
"encode": Common.encodeStatus, "encode": Common.encodeStatus,
"encodeQueueSize": Common.encodeQueue.qsize(),
"upload": Common.uploadStatus, "upload": Common.uploadStatus,
"uploadQueueSize": Common.uploadQueue.qsize(),
"error": Common.errors, "error": Common.errors,
"broadcast": { "broadcast": {
"broadcaster": Common.broadcaster.__str__(), "broadcaster": Common.broadcaster.__str__(),
"isBroadcasting": Common.isBroadcasting, "isBroadcasting": Common.isBroadcasting,
"streamUrl": Common.streamUrl, "streamUrl": Common.streamUrl,
"updateTime": Common.updateTime "updateTime": Common.updateTime
},
"config": {
"forceNotBroadcasting": Common.forceNotBroadcasting,
"forceStopDownload": Common.forceStopDownload,
} }
}}) }})
@app.route("/stats/broadcast", methods=["GET"]) @app.route("/stats/broadcast", methods=["GET"])
def geBroadcastStats(): def getBroadcastStats():
return jsonify({"message":"ok","code":200,"status":0,"data":{ return jsonify({"message":"ok","code":200,"status":0,"data":{
"broadcast": { "broadcast": {
"broadcaster": Common.broadcaster.__str__(), "broadcaster": Common.broadcaster.__str__(),
@ -81,8 +89,18 @@ def geBroadcastStats():
}}) }})
@app.route("/stats/config", methods=["GET"])
def getConfigStats():
return jsonify({"message":"ok","code":200,"status":0,"data":{
"config": {
"forceNotBroadcasting": Common.forceNotBroadcasting,
"forceStopDownload": Common.forceStopDownload,
}
}})
@app.route("/stats/download", methods=["GET"]) @app.route("/stats/download", methods=["GET"])
def geDownloadStats(): def getDownloadStats():
return jsonify({"message":"ok","code":200,"status":0,"data":{ return jsonify({"message":"ok","code":200,"status":0,"data":{
"download":Common.downloadStatus, "download":Common.downloadStatus,
}}) }})
@ -92,6 +110,7 @@ def geDownloadStats():
def getEncodeStats(): def getEncodeStats():
return jsonify({"message":"ok","code":200,"status":0,"data":{ return jsonify({"message":"ok","code":200,"status":0,"data":{
"encode": Common.encodeStatus, "encode": Common.encodeStatus,
"encodeQueueSize": Common.encodeQueue.qsize(),
}}) }})
@ -99,9 +118,30 @@ def getEncodeStats():
def getUploadStats(): def getUploadStats():
return jsonify({"message":"ok","code":200,"status":0,"data":{ return jsonify({"message":"ok","code":200,"status":0,"data":{
"upload": Common.uploadStatus, "upload": Common.uploadStatus,
"uploadQueueSize": Common.uploadQueue.qsize(),
}}) }})
@app.route("/files/", methods=["GET"])
def fileIndex():
a = []
for i in (glob("*.mp4") + glob("*.flv")):
a.append({
"name": i,
"size": Common.parseSize(os.path.getsize(i))
})
return render_template("files.html",files=a)
@app.route("/files/download/<path>", methods=["GET"])
def fileDownload(path):
def generate(file):
with open(file, "rb") as f:
for row in f:
yield row
return Response(generate(path), mimetype='application/octet-stream')
def SubThread(): def SubThread():
t = threading.Thread(target=RUN, args=(Common.config['l_u'],)) t = threading.Thread(target=RUN, args=(Common.config['l_u'],))
t.setDaemon(True) t.setDaemon(True)

View File

@ -4,6 +4,7 @@ import os
import re import re
import json as JSON import json as JSON
from datetime import datetime from datetime import datetime
from time import sleep
from Common import appendUploadStatus, modifyLastUploadStatus from Common import appendUploadStatus, modifyLastUploadStatus
import rsa import rsa
import math import math
@ -11,7 +12,7 @@ import base64
import hashlib import hashlib
import requests import requests
from urllib import parse from urllib import parse
requests.adapters.DEFAULT_RETRIES = 10
class VideoPart: class VideoPart:
def __init__(self, path, title='', desc=''): def __init__(self, path, title='', desc=''):
@ -25,6 +26,7 @@ class Bilibili:
self.files = [] self.files = []
self.videos = [] self.videos = []
self.session = requests.session() self.session = requests.session()
self.session.keep_alive = False
if cookie: if cookie:
self.session.headers["cookie"] = cookie self.session.headers["cookie"] = cookie
self.csrf = re.search('bili_jct=(.*?);', cookie).group(1) self.csrf = re.search('bili_jct=(.*?);', cookie).group(1)
@ -203,6 +205,7 @@ class Bilibili:
filepath = part.path filepath = part.path
filename = os.path.basename(filepath) filename = os.path.basename(filepath)
filesize = os.path.getsize(filepath) filesize = os.path.getsize(filepath)
appendUploadStatus("Upload >{}< Started".format(filepath))
self.files.append(part) self.files.append(part)
r = self.session.get('https://member.bilibili.com/preupload?' r = self.session.get('https://member.bilibili.com/preupload?'
'os=upos&upcdn=ws&name={name}&size={size}&r=upos&profile=ugcupos%2Fyb&ssl=0' 'os=upos&upcdn=ws&name={name}&size={size}&r=upos&profile=ugcupos%2Fyb&ssl=0'
@ -237,12 +240,13 @@ class Bilibili:
# {"upload_id":"72eb747b9650b8c7995fdb0efbdc2bb6","key":"\/i181012ws2wg1tb7tjzswk2voxrwlk1u.mp4","OK":1,"bucket":"ugc"} # {"upload_id":"72eb747b9650b8c7995fdb0efbdc2bb6","key":"\/i181012ws2wg1tb7tjzswk2voxrwlk1u.mp4","OK":1,"bucket":"ugc"}
json = r.json() json = r.json()
upload_id = json['upload_id'] upload_id = json['upload_id']
appendUploadStatus("Upload >{}< Started".format(filepath))
with open(filepath, 'rb') as f: with open(filepath, 'rb') as f:
chunks_num = math.ceil(filesize / chunk_size) chunks_num = math.ceil(filesize / chunk_size)
chunks_index = 0 chunks_index = 0
chunks_data = f.read(chunk_size) chunks_data = f.read(chunk_size)
modifyLastUploadStatus("Uploading >{}< @ {:.2f}%".format(filepath, 100.0 * chunks_index / chunks_num))
while True: while True:
_d = datetime.now()
if not chunks_data: if not chunks_data:
break break
r = self.session.put('https:{endpoint}/{upos_uri}?' r = self.session.put('https:{endpoint}/{upos_uri}?'
@ -265,6 +269,8 @@ class Bilibili:
chunks_data = f.read(chunk_size) chunks_data = f.read(chunk_size)
chunks_index += 1 # start with 0 chunks_index += 1 # start with 0
modifyLastUploadStatus("Uploading >{}< @ {:.2f}%".format(filepath, 100.0*chunks_index/chunks_num)) modifyLastUploadStatus("Uploading >{}< @ {:.2f}%".format(filepath, 100.0*chunks_index/chunks_num))
if (datetime.now()-_d).seconds < 2:
sleep(1)
# NOT DELETE! Refer to https://github.com/comwrg/bilibiliupload/issues/15#issuecomment-424379769 # NOT DELETE! Refer to https://github.com/comwrg/bilibiliupload/issues/15#issuecomment-424379769
self.session.post('https:{endpoint}/{upos_uri}?' self.session.post('https:{endpoint}/{upos_uri}?'
@ -330,7 +336,7 @@ class Bilibili:
"order_id": 0, "order_id": 0,
"videos": self.videos} "videos": self.videos}
) )
appendUploadStatus(">{}< Published | Result : {}".format(title, r.text)) appendUploadStatus("[{}] Published | Result : {}".format(title, r.text))
def reloadFromPrevious(self): def reloadFromPrevious(self):
if os.path.exists("uploaded.json"): if os.path.exists("uploaded.json"):

View File

@ -17,20 +17,20 @@ def download(url):
path = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.flv") path = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.flv")
p = requests.get(url, stream=True) p = requests.get(url, stream=True)
if p.status_code != 200: if p.status_code != 200:
appendDownloadStatus("Download [{}] Response 404 ,will stop looping".format(url)) appendDownloadStatus("Download with Response 404, maybe broadcaster is not broadcasting")
return True return True
isDownload = True isDownload = True
appendDownloadStatus("Starting Download >{}<".format(path)) appendDownloadStatus("Download >{}< Start".format(path))
f = open(path, "wb") f = open(path, "wb")
try: try:
for t in p.iter_content(chunk_size=64 * 1024): for t in p.iter_content(chunk_size=64 * 1024):
if t: if t:
f.write(t) f.write(t)
_size = os.path.getsize(path) _size = os.path.getsize(path)
modifyLastDownloadStatus("Download >{}< @ {:.2f}%".format(path, 100.0 * _size/config["p_s"])) modifyLastDownloadStatus("Downloading >{}< @ {:.2f}%".format(path, 100.0 * _size/config["p_s"]))
if _size > config["p_s"] or forceStopDownload: if _size > config["p_s"] or forceStopDownload:
break break
modifyLastDownloadStatus("Finished Download >{}<".format(path)) modifyLastDownloadStatus("Download >{}< Finished".format(path))
except Exception as e: except Exception as e:
appendError("Download >{}< With Exception {}".format(path, datetime.strftime(datetime.now(), "%y%m%d %H%M"), appendError("Download >{}< With Exception {}".format(path, datetime.strftime(datetime.now(), "%y%m%d %H%M"),
e.__str__())) e.__str__()))
@ -53,10 +53,10 @@ def encode():
i = encodeQueue.get() i = encodeQueue.get()
if os.path.exists(i): if os.path.exists(i):
isEncode = True isEncode = True
appendEncodeStatus("Start Encoding >{}<".format(i)) appendEncodeStatus("Encoding >{}< Start".format(i))
os.system("ffmpeg -i {} -c:v copy -c:a copy -f mp4 {} -y".format(i, i[:13] + ".mp4")) os.system("ffmpeg -i {} -c:v copy -c:a copy -f mp4 {} -y".format(i, i[:13] + ".mp4"))
uploadQueue.put(i[:13] + ".mp4") uploadQueue.put(i[:13] + ".mp4")
modifyLastEncodeStatus("Finished Encoding >{}<".format(i)) modifyLastEncodeStatus("Encode >{}< Finished".format(i))
if config["mv"]: if config["mv"]:
shutil.move(i, config["mtd"]) shutil.move(i, config["mtd"])
elif config["del"]: elif config["del"]:
@ -107,10 +107,10 @@ def run(name):
_count = 0 _count = 0
_count_error = 0 _count_error = 0
while True: while True:
if api.isLive: if api.isLive and not forceNotBroadcasting:
if d is None: if d is None:
d = datetime.strftime(datetime.now(), "%Y_%m_%d") d = datetime.strftime(datetime.now(), "%Y_%m_%d")
if not t.is_alive(): if not t.is_alive() and not forceStopDownload:
_count_error += 1 _count_error += 1
_preT = api.playlist _preT = api.playlist
t = threading.Thread(target=download, args=(_preT,)) t = threading.Thread(target=download, args=(_preT,))

73
static/index.html Normal file
View File

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>录播</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<style type="text/css">
td{
border: solid 1px lightgrey;
}
</style>
</head>
<body>
<div>
<h1>基本信息</h1>
<table>
<tr>
<td>主播名</td>
<td><span id="broadcaster"></span></td>
</tr>
<tr>
<td>是否正在直播</td>
<td><span id="isBroadcasting"></span></td>
</tr>
<tr>
<td>直播视频流地址</td>
<td><span id="streamUrl"></span></td>
</tr>
<tr>
<td>信息更新时间</td>
<td><span id="updateTime"></span></td>
</tr>
</table>
<h1>特殊设置</h1>
<table>
<tr>
<td>是否设置强制认为不直播</td>
<td><span id="forceNotBroadcasting"></span></td>
</tr>
<tr>
<td>是否设置强制不下载</td>
<td><span id="forceStopDownload"></span></td>
</tr>
</table>
<hr/>
<h1>当前状态</h1>
<table>
<tr>
<td>下载日志</td>
<td><span id="download"></span></td>
</tr>
<tr>
<td>转码日志</td>
<td><span id="encode"></span></td>
</tr>
<tr>
<td>上传日志</td>
<td><span id="upload"></span></td>
</tr>
<tr>
<td>错误日志</td>
<td><span id="error"></span></td>
</tr>
<tr>
<td>操作日志</td>
<td><span id="operation"></span></td>
</tr>
</table>
<hr/>
</div>
</body>
<script src="index.js"></script>
</html>

45
static/index.js Normal file
View File

@ -0,0 +1,45 @@
function update(){
$.ajax(
"/stats",
{
success: function (res){
$("#broadcaster").text(res.data.broadcast.broadcaster)
$("#isBroadcasting").text(res.data.broadcast.isBroadcasting)
$("#streamUrl").text(res.data.broadcast.streamUrl)
$("#forceNotBroadcasting").text(res.data.config.forceNotBroadcasting)
$("#forceStopDownload").text(res.data.config.forceStopDownload)
$("#updateTime").text(res.data.broadcast.updateTime)
$("#download").html(function(){
var ret = ""
res.data.download.reverse().forEach(function(obj){
ret += "<tr><td>" + obj.datetime + "</td><td>" + obj.message + "</td></tr>"
})
return "<table>" + ret + "</table>"
})
$("#encode").html(function(){
var ret = ""
res.data.encode.reverse().forEach(function(obj){
ret += "<tr><td>" + obj.datetime + "</td><td>" + obj.message + "</td></tr>"
})
return "<table>" + ret + "</table>"
})
$("#upload").html(function(){
var ret = ""
res.data.upload.reverse().forEach(function(obj){
ret += "<tr><td>" + obj.datetime + "</td><td>" + obj.message + "</td></tr>"
})
return "<table>" + ret + "</table>"
})
$("#error").html(function(){
var ret = ""
res.data.error.reverse().forEach(function(obj){
ret += "<tr><td>" + obj.datetime + "</td><td>" + obj.message + "</td></tr>"
})
return "<table>" + ret + "</table>"
})
}
}
)
}
update()
setInterval(update,10000)

25
templates/files.html Normal file
View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>文件</title>
<style>
td{
border: solid 1px lightgray;
}
</style>
</head>
<body>
<h1>所有录像文件</h1>
<table>
<tr>
<td>文件名</td><td>文件大小</td><td>链接</td>
</tr>
{%for i in files %}
<tr>
<td>{{i.name}}</td><td>{{i.size}}</td><td><a href="/files/download/{{i.name}}">下载文件</a></td>
</tr>
{% endfor %}
</table>
</body>
</html>