ffmpeg命令
::2倍速度 ffmpeg -y -i 1.mp4 -filter:a "atempo=2" -filter:v "setpts=0.5*PTS" out-2-audio.mkv ::0.5倍速度 ffmpeg -y -i 1.mp4 -filter:a "atempo=0.5" -filter:v "setpts=2*PTS" out-half-audio.mkv ::0.25倍速度 ffmpeg -y -i 1.mp4 -filter:a "atempo=0.5,atempo=0.5" -filter:v "setpts=4*PTS" out-half2-audio.mkv
ffmpeg-python调用
self.srcFile= r"C:\Users\Administrator\Desktop\3a.mp4" self.fullOutputVideoFile= r"C:\Users\Administrator\Desktop\xxx5.mp4" self.speed = 4 self.output = '3gp' self.disableAudio = 1 is3gp = self.output.lower() == '3gp' ext = self.fullOutputVideoFile.split('.')[-1] if ext.lower() != self.output: self.fullOutputVideoFile = self.fullOutputVideoFile.replace('.' + ext, '.' + self.output) #是否需要两次转换 audioTwoTimes = False vspeed = 1.0 / self.speed aspeed = self.speed # 如果调速 <0.5 或 >2需要进行两次转换,因为 (0.5 <= atempo <= 2) if aspeed < 0.5 or aspeed > 2: aspeed = aspeed ** 0.5 audioTwoTimes = True input = ffmpeg.input(self.srcFile) if is3gp: #3gp, 音频调速设置 audio = input.audio.filter("atempo", aspeed) if audioTwoTimes: audio = audio.filter("atempo", aspeed) #视频调速设置 video = input.video.filter("setpts", "{}*PTS".format(vspeed)).filter("scale", r"320x240") #音视频混合输出 if self.disableAudio == 0: output = ffmpeg.output(audio, video, self.fullOutputVideoFile, vcodec='libxvid', vb='1200k', acodec='amr_nb', ar=8000, ac=1) else: output = ffmpeg.output(video, self.fullOutputVideoFile, vcodec='libxvid', vb='1200k') print(output.compile()) else: #非3gp, 音频调速设置 audio = input.audio.filter("atempo", aspeed) if audioTwoTimes: audio = audio.filter("atempo", aspeed) #视频调速设置 video = input.video.filter("setpts", "{}*PTS".format(vspeed)) #音视频混合输出 if self.disableAudio == 0: output = ffmpeg.output(audio, video, self.fullOutputVideoFile) else: output = ffmpeg.output(video, self.fullOutputVideoFile) print(output.compile()) #异步执行 proc = output.run_async(pipe_stderr=True, overwrite_output=True) self.totalTime = 0 self.converted = False def callback(line): try: if self.totalTime == 0: mobj = re.search(r'Duration\:\s*((?:\d\d[.:]){3}\d\d)', line) if not mobj: return self.totalTime += parse_dfxp_time_expr(mobj.group(1)) / self.speed else: mobj = re.search(r'time=(.+)\s*bitrate=', line) if not mobj: return self.converted = True convertedDuration = parse_dfxp_time_expr(mobj.group(1)) self.progress = convertedDuration / self.totalTime * 100 print(self.progress) #updateInfo(self.progressFile, self.shortOutputFile, self.progress, 'working') except Exception as ex: self.converted = False print(ex) return runProc(proc, proc.stderr, callback, timeOut=300)
# 增加自动缩进换行 def indent(elem, level=0): i = "\n" + level*" " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " if not elem.tail or not elem.tail.strip(): elem.tail = i for elem in elem: indent(elem, level+1) if not elem.tail or not elem.tail.strip(): elem.tail = i else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i def parse_dfxp_time_expr(time_expr): if not time_expr: return time_expr = time_expr.strip() mobj = re.match(r'^(?P<time_offset>\d+(?:\.\d+)?)s?$', time_expr) if mobj: return float(mobj.group('time_offset')) mobj = re.match(r'^(\d+):(\d\d):(\d\d(?:(?:\.|:)\d+)?)$', time_expr) if mobj: return 3600 * int(mobj.group(1)) + 60 * int(mobj.group(2)) + float(mobj.group(3).replace(':', '.')) def runProc(proc, out, callback, timeOut = 30): try: proc_out_closed = False start = time.time() while not proc_out_closed: if (time.time() - start > timeOut): raise KeyboardInterrupt() line = '' while True: char = out.read(1) if not char: proc_out_closed = True break if char in [b'\r', b'\n']: break try: line += char.decode('ascii', 'replace') except Exception as ex: continue if not line: continue if isinstance(line, bytes): line = line.decode('utf-8') #print(line) #print可能會有特殊字符而引起的異常 callback(line) return proc.wait() == 0 except KeyboardInterrupt: try: if sys.platform != 'win32': proc.communicate(b'q') else: proc.terminate() except: print('except...........') return False def updateInfo(fileName, outputFileName, progress, resultState = 'working', error=None): if os.path.exists(fileName): Tree = ET.parse(fileName) ProgressInfoNode = Tree.getroot() #创建根节点 else: ProgressInfoNode = ET.Element('ProgressInfo') #创建子节点,并添加属性 GetNode = lambda child: ProgressInfoNode.find(child) if ProgressInfoNode.find(child)!=None else ET.SubElement(ProgressInfoNode, child) Node = GetNode('OutputFileName')#ET.SubElement(ProgressInfoNode,'OutputFileName') Node.text = outputFileName Node = GetNode('ResultState')#ET.SubElement(ProgressInfoNode, 'ResultState') Node.text = resultState Node = GetNode('Progress')#ET.SubElement(ProgressInfoNode, 'Progress') Node.text = str(progress) if error: Node = GetNode('error')#ET.SubElement(ProgressInfoNode, 'Progress') Node.text = str(error) #创建elementtree对象,写文件 indent(ProgressInfoNode,0) tree = ET.ElementTree(ProgressInfoNode) tree.write(fileName, encoding="utf-8")