Created
December 21, 2023 15:46
-
-
Save amolok/4913562c5b4c4213865800cbb7014d4f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from __future__ import unicode_literals | |
from __future__ import print_function | |
import sys | |
import os | |
import re | |
from datetime import datetime | |
import time | |
import subprocess | |
DISK = "Y:" | |
FOLDER = "DCIM" | |
FILE = "files.txt" | |
OUT_PATH = os.path.join("M:","Projects","RIMANI","timelapse") | |
bin_path = "C:/Users/amrok/Dropbox/soft/ffmpeg-3.4-win64-static/bin/" | |
# bin_path = "./bin/" | |
# Print iterations progress | |
# ░▒▓█ | |
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '▓', empty = '░', printEnd = "\r"): | |
""" | |
Call in a loop to create terminal progress bar | |
@params: | |
iteration - Required : current iteration (Int) | |
total - Required : total iterations (Int) | |
prefix - Optional : prefix string (Str) | |
suffix - Optional : suffix string (Str) | |
decimals - Optional : positive number of decimals in percent complete (Int) | |
length - Optional : character length of bar (Int) | |
fill - Optional : bar fill character (Str) | |
empty - Optional : bar empty character (Str) | |
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str) | |
""" | |
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) | |
filledLength = int(length * iteration // total) | |
bar = fill * filledLength + empty * (length - filledLength) | |
print(f'\r{prefix} {bar} {percent}% {suffix}', end = printEnd) | |
# Print New Line on Complete | |
if iteration == total: | |
print() | |
def getTimeS(time): | |
h = int(time[0:2]) | |
m = int(time[3:5]) | |
s = int(time[6:8]) | |
ms = int(time[9:11]) | |
ts = (h * 60 * 60) + (m * 60) + s + (ms/60) | |
return int(ts) | |
def time_format(seconds): | |
if seconds < 90: | |
return f"{seconds:.0f}s" | |
elif seconds < 150: | |
return f"{seconds / 60:.1f}m" | |
elif seconds < 3600: | |
minutes = seconds // 60 | |
seconds = seconds % 60 | |
return f"{minutes:02.0f}:{seconds:02.0f}" | |
else: | |
hours = seconds // 3600 | |
minutes = (seconds % 3600) // 60 | |
seconds = seconds % 60 | |
return f"{hours:02.0f}:{minutes:02.0f}:{seconds:02.0f}" | |
# -i g%04d.jpg -an -c:v libx264 -crf 30 -maxrate 1M -bufsize 1M -pix_fmt yuv420p -vf "eq=contrast=1.2:gamma=1.2:saturation=2,scale=800:-1" timelapse.mp4 | |
def create_timelapse(input_file, output_file, total_frames): | |
bitrate = "1M" | |
cmd = subprocess.Popen([bin_path+"ffmpeg", | |
# "-minrate "+bitrate, "-maxrate "+bitrate, "-b:v "+bitrate, | |
"-f", "concat", | |
"-safe", "0", | |
"-i", os.path.join(input_file), | |
"-an", | |
"-c:v", "libx264", | |
"-crf", "30", | |
"-maxrate", "1M", | |
"-bufsize", "1M", | |
"-pix_fmt", "yuv420p", | |
"-vf", "eq=contrast=1.2:gamma=1.2:saturation=2,scale=800:-1", | |
"-y", output_file | |
], | |
stdout=subprocess.PIPE, | |
stderr=subprocess.STDOUT, | |
universal_newlines=True, | |
# shell=True | |
) | |
for line in cmd.stdout: | |
# print(line) | |
# print(str(line.rstrip())) | |
frame = re.search('frame= +([^ ]*)',line) | |
fps = re.search('fps= ?([^ ]*)',line) | |
size = re.search('size= +([^ ]*)',line) | |
# if frame: | |
# print(frame[1]) | |
# if fps: | |
# print(fps[1]) | |
# if size: | |
# print(size[1]) | |
if frame and fps and size: | |
# print(line) | |
# print("f={}, {}fps, {}".format(frame[1], fps[1], size[1])) | |
printProgressBar(int(frame[1]), total_frames, length=60, prefix=" * Собираем кадр {:>7}".format(frame[1]) , suffix="({} fps) размер {}".format(fps[1], size[1])) | |
# cmd.stdout.flush() | |
# print("Записали файл "+filename.upper()+"."+ 60*" ") | |
return cmd.stdout | |
def get_file_list_and_time(directory): | |
file_list = [] | |
earliest_time = None | |
latest_time = None | |
for root, dirs, files in os.walk(directory): | |
# print(" +- {} {} {}".format(root, len(dirs), len(files))) | |
if len(dirs)>0: | |
print(" +- {} папок".format(len(dirs)), end=" "*20+'\r') | |
else: | |
print(" +- {} файлов в папке {}".format(len(files), root), end=" "*20+'\r') | |
for file in files: | |
# print(" + - {} / {}".format(root, file)) | |
if file.endswith(".JPG"): | |
file_path = os.path.join(root, file) | |
# print(" +-> "+file_path) | |
print(" +-> "+file_path, end=" "*20+'\r') | |
file_list.append(file_path) | |
# creation_time = os.path.getctime(file_path) | |
# if earliest_time is None or creation_time < earliest_time: | |
# earliest_time = creation_time | |
# if latest_time is None or creation_time > latest_time: | |
# latest_time = creation_time | |
# print(" += {} файлов нашлось".format(len(file_list))) | |
return [file_list, datetime.fromtimestamp(os.path.getctime(file_list[0])), datetime.fromtimestamp(os.path.getctime(file_list[-1]))] | |
# return [file_list, datetime.fromtimestamp(earliest_time), datetime.fromtimestamp(latest_time)] | |
def save_file_list(file_list, output_file): | |
with open(output_file, 'w') as f: | |
for file in file_list: | |
f.write(file + '\n') | |
def main(): | |
if len(sys.argv)<2: | |
folder = DISK+'\\'+FOLDER | |
else: | |
folder = sys.argv[1] | |
if len(sys.argv)==3: | |
output_file = sys.argv[2] | |
else: | |
output_file = os.path.join(DISK, FILE) | |
start = time.time() | |
print("[ ] Собираем таймлапс из папки: {}".format(folder)) | |
[files, earliest_time, latest_time] = get_file_list_and_time(folder) | |
# file_list = ["file '{}'".format(file) for file in files] | |
file_list = ["file 'file:{}'".format(file) for file in files] | |
# file_list = ["file 'file:{}'".format(file.replace('\\', '/')) for file in files] | |
# file_list = ["file '{}'".format(file.replace(DISK, "").replace("\\", "/")) for file in files] | |
save_file_list(file_list, output_file) | |
timelapse = "timelapse ({} - {}).mp4".format(earliest_time.strftime("%Y-%m-%d"), latest_time.strftime("%Y-%m-%d")) | |
print("[-] Сохраняем в файл {1} в папке {0}".format(OUT_PATH, timelapse)) | |
print("[+] Всего кадров: {:>7}".format(len(files))) | |
create_timelapse(output_file, timelapse, len(file_list)) | |
# create_timelapse(output_file, os.path.join(OUT_PATH, timelapse)) | |
end = time.time() | |
print("[=] Закончили за {}".format(time_format(end - start))) | |
if __name__ == '__main__': | |
print ("Сборка таймлапса с гоупро.") | |
# print ("Первый параметр - откуда брать JPG, второй - название таймлапса. Где брать ffmpeg захардкожено. Работает и без параметров.") | |
print ("t.me/amrok") | |
main() | |
# print() | |
quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment