Skip to content

Commit

Permalink
choice btw 30/60fps and 1pass/2pass corrected bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
MightyPotatoast committed Aug 20, 2021
1 parent 32595a6 commit 50e4e7a
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 45 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
build/
build/
__pycache__
ffmpeg2pass-0.log
ffmpeg2pass-0.log.mbtree
37 changes: 22 additions & 15 deletions compress.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import ffmpeg
import os
os.environ['path'] = 'bin/'
import ffmpeg
def compress_video(video_full_path, size_upper_bound, two_pass=True, filename_suffix='1'):


def compress_video(video_full_path, size_upper_bound, frame_rate=30, two_pass=True, filename_suffix='_compressed'):
"""
Compress video file to max-supported size.
:param video_full_path: the video you want to compress.
:param size_upper_bound: Max video size in KB.
:param frame_rate: Set the video max frame per second.
:param two_pass: Set to True to enable two-pass calculation.
:param filename_suffix: Add a suffix for new video.
:return: out_put_name or error
:return: True if succes, False if error
"""
filename, extension = os.path.splitext(video_full_path)
extension = '.mp4'
output_file_name = filename + filename_suffix + extension

total_bitrate_lower_bound = 11000
min_audio_bitrate = 32000
min_audio_bitrate = 64000
max_audio_bitrate = 256000
min_video_bitrate = 100000

Expand All @@ -25,17 +28,21 @@ def compress_video(video_full_path, size_upper_bound, two_pass=True, filename_su
# Video duration, in s.
duration = float(probe['format']['duration'])
# Audio bitrate, in bps.
audio_bitrate = float(next((s for s in probe['streams'] if s['codec_type'] == 'audio'), None)['bit_rate'])
audio_bitrate = float(next(
(s for s in probe['streams'] if s['codec_type'] == 'audio'), None)['bit_rate'])
# Target total bitrate, in bps.
target_total_bitrate = (size_upper_bound * 1024 * 8) / (1.073741824 * duration)
target_total_bitrate = (
size_upper_bound * 1024 * 8) / (1.073741824 * duration)
if target_total_bitrate < total_bitrate_lower_bound:
print('Bitrate is extremely low! Stop compress!')
return False

# Best min size, in kB.
best_min_size = (min_audio_bitrate + min_video_bitrate) * (1.073741824 * duration) / (8 * 1024)
best_min_size = (min_audio_bitrate + min_video_bitrate) * \
(1.073741824 * duration) / (8 * 1024)
if size_upper_bound < best_min_size:
print('Quality not good! Recommended minimum size:', '{:,}'.format(int(best_min_size)), 'KB.')
print('Quality not good! Recommended minimum size:',
'{:,}'.format(int(best_min_size)), 'KB.')
# return False

# Target audio bitrate, in bps.
Expand All @@ -58,18 +65,17 @@ def compress_video(video_full_path, size_upper_bound, two_pass=True, filename_su
i = ffmpeg.input(video_full_path)
if two_pass:
ffmpeg.output(i, '/dev/null' if os.path.exists('/dev/null') else 'NUL',
**{'c:v': 'libx264', 'b:v': video_bitrate, 'pass': 1, 'f': 'mp4'}
).overwrite_output().run()
ffmpeg.output(i, output_file_name,
**{'c:v': 'libx264', 'b:v': video_bitrate, 'pass': 2, 'c:a': 'aac', 'b:a': audio_bitrate}
**{'r': frame_rate, 'c:v': 'libx264', 'b:v': video_bitrate, 'pass': 1, 'f': 'mp4'}
).overwrite_output().run()
ffmpeg.output(i, output_file_name, **{'r': frame_rate, 'c:v': 'libx264', 'b:v': video_bitrate,
'pass': 2, 'c:a': 'aac', 'b:a': audio_bitrate}).overwrite_output().run()
else:
ffmpeg.output(i, output_file_name,
**{'c:v': 'libx264', 'b:v': video_bitrate, 'c:a': 'aac', 'b:a': audio_bitrate}
**{'r': frame_rate, 'c:v': 'libx264', 'b:v': video_bitrate, 'c:a': 'aac', 'b:a': audio_bitrate}
).overwrite_output().run()

if os.path.getsize(output_file_name) <= size_upper_bound * 1024:
return output_file_name
return True
elif os.path.getsize(output_file_name) < os.path.getsize(video_full_path): # Do it again
return compress_video(output_file_name, size_upper_bound)
else:
Expand All @@ -79,6 +85,7 @@ def compress_video(video_full_path, size_upper_bound, two_pass=True, filename_su
print('You can install ffmpeg by reading https://github.com/kkroening/ffmpeg-python/issues/251')
return False


if __name__ == '__main__':
file_name = compress_video('input.mp4', 50 * 1000)
print(file_name)
print(file_name)
108 changes: 79 additions & 29 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,107 @@
import os
from compress import compress_video


def compress():
r = compress_video(
text_entry.get(), limit_file_size.get(), frame_rate.get(), Npass.get()
)
if r == True:
result_lab.config(text="Done !")
else:
result_lab.config(text='Error')


def browseFiles():
filename = filedialog.askopenfilename(initialdir = "/",title = "Select a File",filetypes = (("Video files","*.mp4*"),("all files","*.*")))
text_entry.insert(1,filename)

def radioRefresh():
filename = filedialog.askopenfilename(
initialdir="/", title="Select a File", filetypes=(("Video files", "*.mp4*"), ("all files", "*.*"))
)
text_entry.delete(0, len(text_entry.get()))
text_entry.insert(0, filename)


def RadioRefreshFileSize():
print(limit_file_size.get())


def RadioRefreshFrameRate():
print(frame_rate.get())


def RadioRefreshPass():
print(Npass)


wind = tk.Tk() # Establishing top level control wind
wind.geometry("250x200") # Set window size
wind.title("Video transcoding") # Set window title

# Create pane title, content, font, color
title_lab = tk.Label(wind, text="Video transcoding", font="Arial 16 bold",width=14)
result_lab = tk.Label(wind, text="", font="Arial 16 bold",width=18)
title_lab = tk.Label(wind, text="Video transcoding",
font="Arial 16 bold", width=14)
result_lab = tk.Label(wind, text="", font="Arial 16 bold", width=18)

# create a frame containing an Entry and the button to explore files
frame2 = Frame(wind)
# Create the input control entry, that is, the form
text_entry = tk.Entry(frame2, width=15, font="Arial 12 bold")
button_explore = tk.Button(frame2,text = "Source file",command = browseFiles)
button_explore = tk.Button(frame2, text="Source file", command=browseFiles)

# create a frame containing 3 radio button for different file size
frame = Frame(wind)
limit_file_size = IntVar()
R1 = tk.Radiobutton(frame, text="8MB", variable=limit_file_size, value=8000,command=radioRefresh)
R2 = tk.Radiobutton(frame, text="50MB", variable=limit_file_size, value=50000,command=radioRefresh)
R3 = tk.Radiobutton(frame, text="100MB", variable=limit_file_size, value=100000,command=radioRefresh)
R1.invoke()
R1 = tk.Radiobutton(frame, text="8MB", variable=limit_file_size,
value=8000, command=RadioRefreshFileSize)
R2 = tk.Radiobutton(frame, text="50MB", variable=limit_file_size,
value=50000, command=RadioRefreshFileSize)
R3 = tk.Radiobutton(frame, text="100MB", variable=limit_file_size,
value=100000, command=RadioRefreshFileSize)
R1.invoke() # R1 is selectionned by default

def compress():
r = compress_video(text_entry.get(), limit_file_size.get())
if r != Exception:
result_lab.config(text="Done !")
else:
result_lab.config(text=str(r))
# create a frame containing 2 radio button for different frame rate
frame3 = Frame(wind)
frame_rate = IntVar()
R_fps30 = tk.Radiobutton(frame3, text="30fps", variable=frame_rate,
value=30, command=RadioRefreshFrameRate)
R_fps60 = tk.Radiobutton(frame3, text="60fps", variable=frame_rate,
value=60, command=RadioRefreshFrameRate)
R_fps30.invoke()

# create a frame containing 2 radio button for different number of passage
frame4 = Frame(wind)
Npass = BooleanVar()
R_2pass = tk.Radiobutton(frame4, text="Slow", variable=Npass,
value=True, command=RadioRefreshPass)
R_1pass = tk.Radiobutton(frame4, text="Fast", variable=Npass,
value=False, command=RadioRefreshPass)

R_1pass.invoke() # R_1pass is selectionned by default

# Set the submit button, and set the font style and size
btn = tk.Button(wind, text="Go !",font="Arial 14 bold", fg="blue", width=8,command=compress)
btn = tk.Button(wind, text="Go !", font="Arial 14 bold",
fg="blue", width=8, command=compress)


title_lab.grid(column=2, row=1) # Set title position

frame2.grid(column=2, row=5)
text_entry.pack(side=LEFT) # Set control location
button_explore.pack(side=LEFT) # Set button position

title_lab.grid(column = 2, row = 1) # Set title position
frame.grid(column=2, row=8)
R1.pack(side=LEFT) # Set control location
R2.pack(side=LEFT) # Set control location
R3.pack(side=LEFT) # Set control location

frame2.grid(column = 2, row = 5)
text_entry.pack(side= LEFT) # Set control location
button_explore.pack(side= LEFT) # Set button position
frame3.grid(column=2, row=9)
R_fps30.pack(side=LEFT) # Set control location
R_fps60.pack(side=LEFT) # Set control location

frame.grid(column = 2, row = 8)
R1.pack(side= LEFT) # Set control location
R2.pack(side= LEFT) # Set control location
R3.pack(side= LEFT) # Set control location
frame4.grid(column=2, row=10)
R_1pass.pack(side=LEFT) # Set control location
R_2pass.pack(side=LEFT) # Set control location

btn.grid(column = 2, row = 9) # Set button position
result_lab.grid(column = 2, row = 10) # Set control location
btn.grid(column=2, row=11) # Set button position
result_lab.grid(column=2, row=12) # Set control location

wind.mainloop() # Message loop of windows
wind.mainloop() # Message loop of windows

0 comments on commit 50e4e7a

Please sign in to comment.