You've already forked my-video-workflow
初次提交
This commit is contained in:
134
controller/api/bilirecorder_blueprint.py
Normal file
134
controller/api/bilirecorder_blueprint.py
Normal file
@ -0,0 +1,134 @@
|
||||
import os.path
|
||||
from datetime import datetime, timedelta
|
||||
from glob import glob
|
||||
from flask import Blueprint, jsonify, request, current_app
|
||||
from typing import Optional
|
||||
|
||||
from config import BILILIVE_RECORDER_DIRECTORY, VIDEO_TITLE
|
||||
from model import db
|
||||
from model.DanmakuClip import DanmakuClip
|
||||
from model.VideoClip import VideoClip
|
||||
from model.Workflow import Workflow
|
||||
|
||||
blueprint = Blueprint("api_bilirecorder", __name__, url_prefix="/api/bilirecorder")
|
||||
|
||||
bili_record_workflow_item: Optional[Workflow] = None
|
||||
|
||||
|
||||
def clear_item():
|
||||
global bili_record_workflow_item
|
||||
bili_record_workflow_item = None
|
||||
|
||||
|
||||
def commit_item():
|
||||
global bili_record_workflow_item
|
||||
if bili_record_workflow_item is None:
|
||||
return
|
||||
bili_record_workflow_item.calculate_start_time()
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def safe_create_item():
|
||||
global bili_record_workflow_item
|
||||
if bili_record_workflow_item is None:
|
||||
bili_record_workflow_item = Workflow.query.filter(
|
||||
Workflow.update_time > (datetime.now() - timedelta(hours=8)),
|
||||
Workflow.automatic == 1
|
||||
).first()
|
||||
if bili_record_workflow_item is None:
|
||||
bili_record_workflow_item = Workflow()
|
||||
else:
|
||||
if bili_record_workflow_item is not None and bili_record_workflow_item.id is not None:
|
||||
bili_record_workflow_item.editing = False
|
||||
commit_item()
|
||||
bili_record_workflow_item = Workflow()
|
||||
if bili_record_workflow_item is None:
|
||||
bili_record_workflow_item = Workflow()
|
||||
bili_record_workflow_item.name = VIDEO_TITLE.format(datetime.now().strftime("%Y%m%d"))
|
||||
bili_record_workflow_item.automatic = True
|
||||
bili_record_workflow_item.editing = True
|
||||
db.session.commit()
|
||||
return bili_record_workflow_item
|
||||
|
||||
|
||||
def safe_get_item() -> Workflow:
|
||||
global bili_record_workflow_item
|
||||
if bili_record_workflow_item is None:
|
||||
return safe_create_item()
|
||||
return bili_record_workflow_item
|
||||
|
||||
|
||||
def collect_danmaku_files(workflow: Optional[Workflow]):
|
||||
if workflow is None:
|
||||
return
|
||||
clip: VideoClip
|
||||
for clip in workflow.video_clips:
|
||||
full_path = clip.full_path
|
||||
pre_file_name = os.path.splitext(full_path)[0]
|
||||
# 理论上也只有一个结果
|
||||
for danmaku_file in glob("{}*xml".format(pre_file_name)):
|
||||
if os.path.exists(danmaku_file):
|
||||
relpath = os.path.relpath(danmaku_file, BILILIVE_RECORDER_DIRECTORY)
|
||||
# 确认是否已经添加
|
||||
already_add = False
|
||||
for danmaku_clip in workflow.danmaku_clips:
|
||||
if danmaku_clip.file == relpath and danmaku_clip.base_path == BILILIVE_RECORDER_DIRECTORY:
|
||||
already_add = True
|
||||
break
|
||||
if not already_add:
|
||||
danmaku = DanmakuClip()
|
||||
danmaku.file = relpath
|
||||
danmaku.base_path = BILILIVE_RECORDER_DIRECTORY
|
||||
danmaku.offset = 0
|
||||
danmaku.workflow = workflow
|
||||
db.session.add(danmaku)
|
||||
workflow.danmaku_clips.append(danmaku)
|
||||
commit_item()
|
||||
|
||||
|
||||
|
||||
@blueprint.post("/")
|
||||
def bilirecorder_event():
|
||||
payload = request.json
|
||||
current_app.logger.debug(payload)
|
||||
if 'EventType' not in payload:
|
||||
response = jsonify({
|
||||
'error': "异常",
|
||||
'payload': payload,
|
||||
})
|
||||
response.status_code = 403
|
||||
return response
|
||||
|
||||
if payload['EventType'] == "SessionStarted":
|
||||
# 录制开始
|
||||
safe_create_item()
|
||||
elif payload['EventType'] == "SessionEnded":
|
||||
# 录制结束
|
||||
item = safe_get_item()
|
||||
item.editing = False
|
||||
commit_item()
|
||||
clear_item()
|
||||
return jsonify(item.to_dict())
|
||||
elif payload['EventType'] == "FileClosed":
|
||||
# 文件关闭
|
||||
item = safe_get_item()
|
||||
event_data = payload.get("EventData", {})
|
||||
video_file = event_data.get("RelativePath", None)
|
||||
# 判断是否重复
|
||||
already_add = False
|
||||
for clip in item.video_clips:
|
||||
if video_file == clip.file and clip.base_path == BILILIVE_RECORDER_DIRECTORY:
|
||||
already_add = True
|
||||
break
|
||||
if not already_add:
|
||||
video_clip = VideoClip()
|
||||
video_clip.file = video_file
|
||||
video_clip.base_path = BILILIVE_RECORDER_DIRECTORY
|
||||
video_clip.duration = event_data.get("Duration", 0)
|
||||
item.video_clips.append(video_clip)
|
||||
commit_item()
|
||||
collect_danmaku_files(item)
|
||||
return jsonify(item.to_dict())
|
||||
commit_item()
|
||||
item = safe_get_item()
|
||||
return jsonify(item.to_dict())
|
20
controller/api/collector_blueprint.py
Normal file
20
controller/api/collector_blueprint.py
Normal file
@ -0,0 +1,20 @@
|
||||
import platform
|
||||
|
||||
from flask import Blueprint, jsonify
|
||||
from util.system import check_exec
|
||||
from config import DANMAKU_FACTORY_EXEC, FFMPEG_EXEC
|
||||
|
||||
blueprint = Blueprint("api_collector", __name__, url_prefix="/api/collector")
|
||||
|
||||
|
||||
@blueprint.get("/")
|
||||
def collect_basic_status():
|
||||
return jsonify({
|
||||
'exec': {
|
||||
'ffmpeg': check_exec(FFMPEG_EXEC),
|
||||
'danmaku': check_exec(DANMAKU_FACTORY_EXEC),
|
||||
},
|
||||
'system': {
|
||||
'os': platform.system(),
|
||||
}
|
||||
})
|
29
controller/api/config_blueprint.py
Normal file
29
controller/api/config_blueprint.py
Normal file
@ -0,0 +1,29 @@
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
from config import get_config, write_config, load_config
|
||||
|
||||
blueprint = Blueprint("api_config", __name__, url_prefix="/api/config")
|
||||
|
||||
|
||||
@blueprint.get("/")
|
||||
def get_global_config():
|
||||
return jsonify(get_config())
|
||||
|
||||
|
||||
@blueprint.put("/")
|
||||
def modify_global_config():
|
||||
return jsonify(request.json)
|
||||
|
||||
|
||||
@blueprint.post("/write")
|
||||
def write_global_config():
|
||||
return jsonify({
|
||||
"result": write_config()
|
||||
})
|
||||
|
||||
|
||||
@blueprint.post("/load")
|
||||
def load_global_config():
|
||||
return jsonify({
|
||||
"result": load_config()
|
||||
})
|
32
controller/api/workflow_blueprint.py
Normal file
32
controller/api/workflow_blueprint.py
Normal file
@ -0,0 +1,32 @@
|
||||
from flask import Blueprint, jsonify
|
||||
|
||||
from model.Workflow import Workflow
|
||||
from model import db
|
||||
|
||||
blueprint = Blueprint("api_workflow", __name__, url_prefix="/api/workflow")
|
||||
|
||||
|
||||
@blueprint.get("/")
|
||||
def get_workflow_list():
|
||||
workflows = Workflow.query.all()
|
||||
return jsonify([d.to_dict() for d in workflows])
|
||||
|
||||
|
||||
@blueprint.get("/<int:workflow_id>")
|
||||
def get_workflow_info(workflow_id):
|
||||
workflow = Workflow.get(workflow_id)
|
||||
return jsonify(workflow)
|
||||
|
||||
|
||||
@blueprint.put("/<int:workflow_id>/done")
|
||||
def done_editing(workflow_id):
|
||||
workflow = Workflow.get(workflow_id)
|
||||
return jsonify(workflow.to_dict())
|
||||
|
||||
|
||||
@blueprint.post("/<int:workflow_id>/queue")
|
||||
def add_to_queue(workflow_id):
|
||||
# JOB_QUEUE.put(workflow_item)
|
||||
return jsonify({
|
||||
'id': workflow_id,
|
||||
})
|
8
controller/view/main_blueprint.py
Normal file
8
controller/view/main_blueprint.py
Normal file
@ -0,0 +1,8 @@
|
||||
from flask import Blueprint, render_template
|
||||
|
||||
blueprint = Blueprint("view_main", __name__, url_prefix="/")
|
||||
|
||||
|
||||
@blueprint.route("/")
|
||||
def main_page():
|
||||
return render_template("index.html")
|
Reference in New Issue
Block a user