-
Notifications
You must be signed in to change notification settings - Fork 1
/
trcode.py
161 lines (134 loc) · 4.86 KB
/
trcode.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""
转码模块
>> 对指定文件进行压制
>> 监控 ffmpeg 输出信息
>> 发送相应事件
>> TODO 可以定义参数
"""
from eventManager import Event
from taskslist import TRANSCODE
from resquest_test import TtranscodeOut
import re,math,subprocess
from log import logger
class transcode:
"""
转码模块
-------
用于对指定媒体文件进行转码:
"""
def __init__(self,eventManager):
self.__eventManager = eventManager
self.pros = 0
self.__active = True
def sendEvent(self,msg,**dt):
"""
事件发送器
---------
封装一个常用的事件发送方法
"""
event = Event(type_=msg)
event.dict["artical"] = TtranscodeOut(**dt)
self.__eventManager.SendEvent(event)
def get_seconds(self,time):
"""
返回日志切片器
-------------
用于对ffmpeg 的输出日志进行相关切片操作
"""
h = int(time[0:2])
m = int(time[3:5])
s = int(time[6:8])
ms = int(time[9:12])
ts = (h * 60 * 60) + (m * 60) + s + (ms / 1000)
return ts
def compute_progress_and_send_progress(self,process,tasksid):
"""
日志解析器
---------
通过正则匹配进行日志解析,获取相关数据
"""
duration = None
while process.poll() is None:
line = process.stderr.readline().strip()
if line:
duration_res = re.search(r'Duration: (?P<duration>\S+)', line)
if duration_res is not None:
duration = duration_res.groupdict()['duration']
duration = re.sub(r',', '', duration)
result = re.search(r'time=(?P<time>\S+)', line)
if result is not None and duration is not None:
elapsed_time = result.groupdict()['time']
currentTime = self.get_seconds(elapsed_time)
allTime = self.get_seconds(duration)
progress = currentTime * 100/allTime
progress = math.ceil(progress)
if progress > 100:
progress = 100
if progress != self.pros:
self.sendEvent("IsTranscode",tasksid = tasksid,progress = progress)
self.pros = progress
# print(f"当前压制进度:{progress}%")
def do_ffmpeg_transcode(self,cmd,tasksid):
"""
ffmpeg 核心
----------
用于驱动FFmpeg 同时触发部分事件
"""
try:
process=subprocess.Popen(cmd,stderr=subprocess.PIPE,bufsize=0,universal_newlines=True,shell=True,encoding="ISO-8859-1")
self.compute_progress_and_send_progress(process,tasksid)
if process.returncode == 0:
self.sendEvent("TranscodeEnded",tasksid = tasksid)
return "success" ,process
else:
self.sendEvent("TranscodeError",tasksid = tasksid)
return "error" ,process
except:
self.sendEvent("TranscodeError",tasksid = tasksid)
def cmd_command(self,Origin,OutPut):
"""
生成cmd命令
"""
from configparser import ConfigParser
config = ConfigParser()
config.read('config.ini',encoding='utf-8')
transcode_config = config['TRANSCODE']
model = transcode_config['model']
encoder = transcode_config['encoder']
crf = transcode_config['crf']
cq = transcode_config['cq']
Bitrate = transcode_config['Bitrate']
bufsize = transcode_config['bufsize']
preset = transcode_config['preset']
# 选择编码器
if encoder == "X264":
encoder = "libx264"
else:
logger.error("不支持的编码器")
raise TypeError("不支持的编码器")
bz = ""
if model == "CRF":
model = f"-crf {crf}"
elif model == "CQ":
model = f"-qp {cq}"
elif model == "B":
model = f"-b {Bitrate}k"
elif model == "VBR":
model = ""
bz = f"-bufsize {bufsize}k"
elif model == "ABR":
model = f"-b:v {Bitrate}k"
bz = f"-bufsize {bufsize}k"
cmd = f"ffmpeg -y -i {Origin} -vcodec {encoder} -preset {preset} {model} {bz} {OutPut}"
return cmd
def transcode_manege(self,task):
"""
转码管理模块
-----------
管理转码,从任务队列中获取任务
进行基本数据解析
"""
self.sendEvent("TranscodeStarted",tasksid = task.TaskId)
cmd = self.cmd_command(task.Origin,task.OutPut)
logger.debug(f"生成转码命令:{cmd}")
self.do_ffmpeg_transcode(cmd,task.TaskId)