Апдейт #2

This commit is contained in:
2025-01-29 04:32:59 +03:00
parent ece1b2e927
commit 1fe5aa8dd1

77
main.py
View File

@ -14,7 +14,10 @@ OUTPUT_DIR = PATH / 'output'
OUTPUT_ARGS: dict[str, Any] = { OUTPUT_ARGS: dict[str, Any] = {
'row-mt': 1, '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): def compress(input_file: Path, output_file: Path, sticker_width: int, max_size: int):
file_input = ffmpeg.input(input_file) 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 = file_input.fps(fps=25, round='up')
stream = stream.scale(w=sticker_width, h=-1, force_original_aspect_ratio='decrease') stream = stream.scale(w=sticker_width, h=-1, force_original_aspect_ratio='decrease')
stream = stream.loop(loop=0)
stream = stream.crop( stream = stream.crop(
out_w=f'min(min(iw,ih),{sticker_width})', out_h=f'min(min(iw,ih),{sticker_width})' 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'): if input_file.suffix in ('.gif', '.mp4'):
duration = float(ffmpeg.probe(input_file)['streams'][0]['duration']) duration = float(ffmpeg.probe(input_file)['streams'][0]['duration'])
max_bitrate = int(max_size * 8 / duration) * .95
speed_factor = 1 speed_factor = 1
if duration > 3: if duration > 3:
speed_factor = duration / 3 speed_factor = duration / 3
stream = stream.setpts(expr=f'PTS*{speed_factor}') 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 = stream.output(
stream, filename=output_file,
filename=file_output,
vcodec='libvpx-vp9', vcodec='libvpx-vp9',
pix_fmt='yuva420p', pix_fmt='yuva420p',
extra_options=OUTPUT_ARGS, an=True,
extra_options=args,
) )
stream.run(overwrite_output=True)
try: file_size = output_file.stat().st_size
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
if file_size / 1024 > max_size: if file_size / 1024 > max_size:
initial_duration = float(ffmpeg.probe(input_file)['format']['duration']) print(stream.compile_line())
bitrate = int(max_size * 8 / initial_duration * .65) logger.info(
f'Average bitrate: {(int(ffmpeg.probe(output_file)['format']['bit_rate']) / 1024):.2f} KB/s'
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,
) )
logger.error(
output.run(overwrite_output=True) f'File size ({file_size / 1024:.2f} KB) exceeds the maximum size ({max_size} KB).'
)
file_output.unlink() exit(1)
temp_output.rename(output_file)
def main(): def main():
@ -109,9 +103,12 @@ def main():
size = 256 size = 256
started_at = time() started_at = time()
files = list(INPUT_DIR.iterdir())
for file in INPUT_DIR.iterdir(): html = '<html><head><style>body { background-color: gray; }</style></head><body>\n'
logger.info(f'Processing {file.name}...')
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'): if file.suffix not in ('.png', '.jpg', '.webp', '.gif', '.mp4'):
logger.warning(f'Unsupported file type: {file.suffix}') logger.warning(f'Unsupported file type: {file.suffix}')
@ -120,10 +117,18 @@ def main():
file_path = INPUT_DIR / file.name file_path = INPUT_DIR / file.name
file_output = OUTPUT_DIR / file.name.replace(file.suffix, '.webm') 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'<video width="250" height="250" src="{file.name.replace(file.suffix, '.webm')}" autoplay loop></video>\n'
logger.info(f'Finished in {round(time() - started_at, 2)} seconds') logger.info(f'Finished in {round(time() - started_at, 2)} seconds')
html += '</body>\n'
html += '</html>\n'
with open(OUTPUT_DIR / 'index.html', 'w', encoding='utf-8') as f:
f.write(html)
if __name__ == '__main__': if __name__ == '__main__':
configure_logging() configure_logging()