diff --git a/main.py b/main.py index d6838f3..d340958 100644 --- a/main.py +++ b/main.py @@ -14,7 +14,10 @@ OUTPUT_DIR = PATH / 'output' OUTPUT_ARGS: dict[str, Any] = { 'row-mt': 1, - 'loglevel': 'error', + 'loglevel': 'warning', + 'max-intra-rate': 100, + 'quality': 'default', + 'auto-alt-ref': 1, } @@ -23,61 +26,52 @@ logger = getLogger(__name__) def compress(input_file: Path, output_file: Path, sticker_width: int, max_size: int): file_input = ffmpeg.input(input_file) - file_output = OUTPUT_DIR / input_file.name.replace(input_file.suffix, '.webm') + + args = OUTPUT_ARGS.copy() stream = file_input.fps(fps=25, round='up') stream = stream.scale(w=sticker_width, h=-1, force_original_aspect_ratio='decrease') - stream = stream.loop(loop=0) stream = stream.crop( out_w=f'min(min(iw,ih),{sticker_width})', out_h=f'min(min(iw,ih),{sticker_width})' ) - stream = stream.pad(color='0x00000000') if input_file.suffix in ('.gif', '.mp4'): duration = float(ffmpeg.probe(input_file)['streams'][0]['duration']) + max_bitrate = int(max_size * 8 / duration) * .95 speed_factor = 1 if duration > 3: speed_factor = duration / 3 stream = stream.setpts(expr=f'PTS*{speed_factor}') + args = args | { + 'minrate': f'{(max_bitrate * .2):.2f}k', + 'maxrate': f'{max_bitrate:.2f}k', + 'b:v': f'{(max_bitrate * .65):.2f}k', + } + else: + args = args | {'crf': 0} - output = ffmpeg.output( - stream, - filename=file_output, + stream = stream.output( + filename=output_file, vcodec='libvpx-vp9', pix_fmt='yuva420p', - extra_options=OUTPUT_ARGS, + an=True, + extra_options=args, ) + stream.run(overwrite_output=True) - try: - output.run(overwrite_output=True) - except Exception as e: - logger.error(f"Error during first encoding: {e}") - exit(1) - - file_size = file_output.stat().st_size + file_size = output_file.stat().st_size if file_size / 1024 > max_size: - initial_duration = float(ffmpeg.probe(input_file)['format']['duration']) - bitrate = int(max_size * 8 / initial_duration * .65) - - temp_output = file_output.with_suffix('.tmp.webm') - stream = ffmpeg.input(output_file, c='libvpx-vp9') - - output = ffmpeg.output( - stream, - filename=temp_output, - vcodec='libvpx-vp9', - pix_fmt='yuva420p', - b=f'{bitrate}k', - extra_options=OUTPUT_ARGS, + print(stream.compile_line()) + logger.info( + f'Average bitrate: {(int(ffmpeg.probe(output_file)['format']['bit_rate']) / 1024):.2f} KB/s' ) - - output.run(overwrite_output=True) - - file_output.unlink() - temp_output.rename(output_file) + logger.error( + f'File size ({file_size / 1024:.2f} KB) exceeds the maximum size ({max_size} KB).' + ) + exit(1) def main(): @@ -109,9 +103,12 @@ def main(): size = 256 started_at = time() + files = list(INPUT_DIR.iterdir()) - for file in INPUT_DIR.iterdir(): - logger.info(f'Processing {file.name}...') + html = '
\n' + + for i, file in enumerate(files): + logger.info(f'Processing [{i+1}/{len(list(files))}] {file.name}...') if file.suffix not in ('.png', '.jpg', '.webp', '.gif', '.mp4'): logger.warning(f'Unsupported file type: {file.suffix}') @@ -120,10 +117,18 @@ def main(): file_path = INPUT_DIR / file.name file_output = OUTPUT_DIR / file.name.replace(file.suffix, '.webm') - compress(file_path, file_output, width, size) + compress(file_path.relative_to(PATH), file_output.relative_to(PATH), width, size) + + html += f'\n' logger.info(f'Finished in {round(time() - started_at, 2)} seconds') + html += '\n' + html += '\n' + + with open(OUTPUT_DIR / 'index.html', 'w', encoding='utf-8') as f: + f.write(html) + if __name__ == '__main__': configure_logging()