Av1an/av1an/ffmpeg.py
2020-12-25 17:32:45 +02:00

92 lines
2.8 KiB
Python
Executable file

#!/bin/env python
import re
import subprocess
from pathlib import Path
from subprocess import PIPE, STDOUT
from typing import List
from .logger import log
def frame_probe_ffmpeg(source: Path):
"""
Get frame count.
Direct counting of frame count using ffmpeg. Slow, Precise.
:param: source: Path to input file
"""
cmd = ["ffmpeg", "-hide_banner", "-i", source.as_posix(), "-map", "0:v:0", "-f", "null", "-"]
r = subprocess.run(cmd, stdout=PIPE, stderr=PIPE)
matches = re.findall(r"frame=\s*([0-9]+)\s", r.stderr.decode("utf-8") + r.stdout.decode("utf-8"))
return int(matches[-1])
def get_frametypes(file: Path) -> List:
"""
Read file and return list with all frame types
:param file: Path for file
:return: list with sequence of frame types
"""
frames = []
ff = ["ffmpeg", "-hide_banner", "-i", file.as_posix(),
"-vf", "showinfo", "-f", "null", "-loglevel", "debug", "-"]
pipe = subprocess.Popen(ff, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
line = pipe.stdout.readline().strip().decode("utf-8")
if len(line) == 0 and pipe.poll() is not None:
break
frames.append(line)
return frames
def get_keyframes(file: Path) -> List[int]:
"""
Read file info and return list of all keyframes
:param file: Path for input file
:return: list with frame numbers of keyframes
"""
keyframes = []
ff = ["ffmpeg", "-hide_banner", "-i", file.as_posix(),
"-vf", r"select=eq(pict_type\,PICT_TYPE_I)",
"-f", "null", "-loglevel", "debug", "-"]
pipe = subprocess.Popen(ff, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
line = pipe.stdout.readline().strip().decode("utf-8")
if len(line) == 0 and pipe.poll() is not None:
break
match = re.search(r"n:([0-9]+)\.[0-9]+ pts:.+key:1", line)
if match:
keyframe = int(match.group(1))
keyframes.append(keyframe)
return keyframes
def extract_audio(input_vid: Path, temp, audio_params):
"""Extracting audio from source, transcoding if needed."""
log(f'Audio processing\nParams: {" ".join(audio_params)}\n')
audio_file = temp / 'audio.mkv'
# Checking is source have audio track
check = ['ffmpeg', '-y', '-hide_banner', '-loglevel', 'error', '-ss', '0', '-i', input_vid.as_posix(), '-t', '0',
'-vn', '-c:a', 'copy', '-f', 'null', '-']
is_audio_here = len(subprocess.run(check, stdout=PIPE, stderr=STDOUT).stdout) == 0
# If source have audio track - process it
if is_audio_here:
cmd = ('ffmpeg', '-y', '-hide_banner', '-loglevel', 'error', '-i', input_vid.as_posix(), '-map_metadata', '0',
'-map', '0', '-c', 'copy', '-vn', *audio_params, audio_file.as_posix())
subprocess.run(cmd)