Skip to content

Commit

Permalink
warn when file is too short, fixes slhck#87
Browse files Browse the repository at this point in the history
  • Loading branch information
slhck authored and auricgoldfinger committed Dec 15, 2020
1 parent 55aa6dd commit 0db19fa
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 9 deletions.
11 changes: 5 additions & 6 deletions ffmpeg_normalize/_cmd_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
CUR_OS.startswith(i) for i in
['CYGWIN', 'MSYS', 'Linux', 'Darwin', 'SunOS', 'FreeBSD', 'NetBSD'])
NUL = 'NUL' if IS_WIN else '/dev/null'
DUR_REGEX = re.compile(r'Duration: (?P<hour>\d{2}):(?P<min>\d{2}):(?P<sec>\d{2})\.(?P<ms>\d{2})')
TIME_REGEX = re.compile(r'out_time=(?P<hour>\d{2}):(?P<min>\d{2}):(?P<sec>\d{2})\.(?P<ms>\d{2})')

# https://gist.github.com/Hellowlol/5f8545e999259b4371c91ac223409209
def to_ms(s=None, des=None, **kwargs):
Expand All @@ -35,9 +37,6 @@ def to_ms(s=None, des=None, **kwargs):
return result

class CommandRunner():
DUR_REGEX = re.compile(r'Duration: (?P<hour>\d{2}):(?P<min>\d{2}):(?P<sec>\d{2})\.(?P<ms>\d{2})')
TIME_REGEX = re.compile(r'out_time=(?P<hour>\d{2}):(?P<min>\d{2}):(?P<sec>\d{2})\.(?P<ms>\d{2})')

def __init__(self, cmd, dry=False):
self.cmd = cmd
self.dry = dry
Expand Down Expand Up @@ -76,12 +75,12 @@ def run_ffmpeg_command(self):
stderr.append(line.strip())
self.output = "\n".join(stderr)

if not total_dur and CommandRunner.DUR_REGEX.search(line):
total_dur = CommandRunner.DUR_REGEX.search(line).groupdict()
if not total_dur and DUR_REGEX.search(line):
total_dur = DUR_REGEX.search(line).groupdict()
total_dur = to_ms(**total_dur)
continue
if total_dur:
result = CommandRunner.TIME_REGEX.search(line)
result = TIME_REGEX.search(line)
if result:
elapsed_time = to_ms(**result.groupdict())
yield int(elapsed_time / total_dur * 100)
Expand Down
11 changes: 9 additions & 2 deletions ffmpeg_normalize/_media_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from ._streams import AudioStream, VideoStream, SubtitleStream
from ._errors import FFmpegNormalizeError
from ._cmd_utils import NUL, CommandRunner
from ._cmd_utils import NUL, CommandRunner, DUR_REGEX, to_ms
from ._logger import setup_custom_logger
logger = setup_custom_logger('ffmpeg_normalize')

Expand Down Expand Up @@ -69,8 +69,14 @@ def parse_streams(self):

output_lines = [line.strip() for line in output.split('\n')]

duration = None
for line in output_lines:

if 'Duration' in line:
duration = DUR_REGEX.search(line).groupdict()
duration = to_ms(**duration) / 1000
logger.debug("Found duration: " + str(duration) + " s")

if not line.startswith('Stream'):
continue

Expand All @@ -82,13 +88,14 @@ def parse_streams(self):
else:
continue


if 'Audio' in line:
logger.debug("Found audio stream at index {}".format(stream_id))
sample_rate_match = re.search(r'(\d+) Hz', line)
sample_rate = int(sample_rate_match.group(1)) if sample_rate_match else None
bit_depth_match = re.search(r's(\d+)p?,', line)
bit_depth = int(bit_depth_match.group(1)) if bit_depth_match else None
self.streams['audio'][stream_id] = AudioStream(self, stream_id, sample_rate, bit_depth)
self.streams['audio'][stream_id] = AudioStream(self, stream_id, sample_rate, bit_depth, duration)

elif 'Video' in line:
logger.debug("Found video stream at index {}".format(stream_id))
Expand Down
10 changes: 9 additions & 1 deletion ffmpeg_normalize/_streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(self, media_file, stream_id):
super(SubtitleStream, self).__init__(media_file, 'subtitle', stream_id)

class AudioStream(MediaStream):
def __init__(self, media_file, stream_id, sample_rate=None, bit_depth=None):
def __init__(self, media_file, stream_id, sample_rate=None, bit_depth=None, duration=None):
super(AudioStream, self).__init__(media_file, 'audio', stream_id)

self.loudness_statistics = {
Expand All @@ -44,6 +44,14 @@ def __init__(self, media_file, stream_id, sample_rate=None, bit_depth=None):

self.sample_rate = sample_rate
self.bit_depth = bit_depth
self.duration = duration

if self.duration and self.duration <= 3:
logger.warn(
"Audio stream has a duration of less than 3 seconds. "
"Normalization may not work. "
"See https://github.com/slhck/ffmpeg-normalize/issues/87 for more info."
)

def __repr__(self):
return "<{}, audio stream {}>".format(
Expand Down
4 changes: 4 additions & 0 deletions test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ def test_progress(self):
self.assertTrue("100" in output)
self.assertTrue(os.path.isfile('normalized/test.mkv'))

def test_duration(self):
output, _ = ffmpeg_normalize_call(['test/test.wav', '--debug'])
self.assertTrue("Found duration: " in output)

def tearDown(self):
for file in ['test.mkv', 'test.wav', 'test.mp3', 'test.aac', 'test.mp4']:
if os.path.isfile('normalized/' + file):
Expand Down

0 comments on commit 0db19fa

Please sign in to comment.