横版视频改竖版 v1.1
软件运行环境:Win10 及以上,只支持调用 CPU 处理。
软件功能
批量将横屏视频缩放为竖屏,并随机从壁纸文件夹中选择壁纸作为背景。导出的视频保持竖屏 1080x1920 分辨率,输出到视频文件夹中的 output 文件夹。



安装说明
在运行之前,你需要先安装 ImageMagick,MoviePy 会调用它进行处理。同时,ImageMagick 中已经包含 ffmpeg
代码
import os
import random
import tkinter as tk
from ctypes import windll
from tkinter import filedialog, messagebox
from moviepy.editor import VideoFileClip, ImageClip, CompositeVideoClip
from PIL import Image
import concurrent.futures
import threading
windll.shcore.SetProcessDpiAwareness(2)
root = tk.Tk()
root.title('横版视频改竖版 v1.1')
root.geometry('600x650')
root.configure(bg='#f0f0f0')
root.attributes("-alpha", 0.9)
video_folder = ""
wallpaper_folder = ""
output_folder = ""
bitrate_value = "1800k"
def select_video_folder():
global video_folder
video_folder = filedialog.askdirectory()
if video_folder:
text_video_paths.delete(1.0, tk.END)
video_files = [f for f in os.listdir(video_folder) if f.lower().endswith(('.mp4', '.mov'))]
for video_file in video_files:
text_video_paths.insert(tk.END, video_file + '\n', "tag_1")
def select_wallpaper_folder():
global wallpaper_folder
wallpaper_folder = filedialog.askdirectory()
if wallpaper_folder:
print("壁纸文件夹选择:", wallpaper_folder)
def prepare_wallpaper(wallpaper_path):
with Image.open(wallpaper_path) as img:
original_width, original_height = img.size
if original_width == 1080 and original_height == 1920:
return wallpaper_path
scale_ratio = max(1080 / original_width, 1920 / original_height)
new_width = int(original_width * scale_ratio)
new_height = int(original_height * scale_ratio)
img = img.resize((new_width, new_height), Image.LANCZOS)
left = (new_width - 1080) // 2
top = (new_height - 1920) // 2
right = left + 1080
bottom = top + 1920
img = img.crop((left, top, right, bottom))
img.save(wallpaper_path)
return wallpaper_path
def process_videos_thread():
process_videos()
def process_videos():
global output_folder
if not video_folder or not wallpaper_folder:
messagebox.showerror("错误", "请先选择视频和壁纸文件夹。")
return
output_folder = os.path.join(video_folder, "output")
os.makedirs(output_folder, exist_ok=True)
video_files = [f for f in os.listdir(video_folder) if f.lower().endswith(('.mp4', '.mov'))]
num_files = len(video_files)
if num_files < 2:
num_threads = 1
elif 2 <= num_files < 4:
num_threads = 2
else:
num_threads = 4
with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
futures = {executor.submit(process_single_video, video_file, output_folder): video_file for video_file in video_files}
for future in concurrent.futures.as_completed(futures):
video_file = futures[future]
try:
future.result()
except Exception as e:
messagebox.showerror("处理错误", f"处理视频 {video_file} 时出错: {e}")
text_video_paths.insert(tk.END, '已处理完成全部\n', "tag_1")
def process_single_video(video_file, output_folder):
video_path = os.path.join(video_folder, video_file)
with VideoFileClip(video_path) as video:
if video.size[0] > video.size[1]:
wallpaper_file = random.choice(os.listdir(wallpaper_folder))
wallpaper_path = os.path.join(wallpaper_folder, wallpaper_file)
prepared_wallpaper_path = prepare_wallpaper(wallpaper_path)
with ImageClip(prepared_wallpaper_path) as wallpaper:
video_resized = video.resize(width=1080)
x_position = (1080 - video_resized.size[0]) / 2
y_position = (1920 - video_resized.size[1]) / 2
final_clip = CompositeVideoClip([
wallpaper.set_duration(video.duration).set_position("center"),
video_resized.set_position((x_position, y_position))
])
output_path = os.path.join(output_folder, f"{os.path.splitext(video_file)[0]}_竖.mp4")
selected_bitrate = bitrate_entry.get() or bitrate_value
final_clip.write_videofile(output_path, codec='libx264', bitrate=selected_bitrate)
text_video_paths.insert(tk.END, f'已处理完成{video_file}\n', "tag_2")
def open_output_folder():
global output_folder
if os.path.exists(output_folder):
os.startfile(output_folder)
button_frame1 = tk.Frame(root, bg='#f0f0f0')
button_frame1.pack(pady=5)
btn_select_video = tk.Button(button_frame1, text='选择视频文件夹', bg='#4CAF50', fg='white', command=select_video_folder, font=('simhei.ttf', 12, 'bold'), relief=tk.FLAT)
btn_select_video.pack(side=tk.LEFT, padx=10)
btn_select_wallpaper = tk.Button(button_frame1, text='选择壁纸文件夹', bg='#4CAF50', fg='white', command=select_wallpaper_folder, font=('simhei.ttf', 12, 'bold'), relief=tk.FLAT)
btn_select_wallpaper.pack(side=tk.LEFT, padx=10)
button_frame2 = tk.Frame(root, bg='#f0f0f0')
button_frame2.pack(pady=5)
btn_start = tk.Button(button_frame2, text='点击此开始处理', bg='#2196F3', fg='white', command=lambda: threading.Thread(target=process_videos_thread).start(), font=('simhei.ttf', 12, 'bold'), relief=tk.FLAT)
btn_start.pack(side=tk.LEFT, padx=10)
btn_open_folder = tk.Button(button_frame2, text='打开输出文件夹', bg='#FFC107', fg='white', command=open_output_folder, font=('simhei.ttf', 12, 'bold'), relief=tk.FLAT)
btn_open_folder.pack(side=tk.LEFT, padx=10)
button_frame3 = tk.Frame(root, bg='#f0f0f0')
button_frame3.pack(pady=5)
bitrate_label = tk.Label(button_frame3, text="导出码率:", bg='#f0f0f0', font=('simhei.ttf', 12))
bitrate_label.pack(side=tk.LEFT, padx=10)
bitrate_entry = tk.Entry(button_frame3, width=10, font=('simhei.ttf', 12))
bitrate_entry.pack(side=tk.LEFT, padx=10)
bitrate_entry.insert(0, bitrate_value)
readme = '''
2024.09.21 吾爱破解 rootcup
批量将竖版视频缩放成横屏,背景图片随机抽取选择文件夹内的图片
使用方法:先选中要批量处理的视频文件夹,再选择背景壁纸文件夹
导出的视频在选择的视频文件夹 output里
2024.09.23 更新:增加选框,可自定义填写导出码率
'''
text_video_paths = tk.Text(root, height=30, width=80, bg='#f0f0f0', font=('simhei.ttf', 10))
text_video_paths.pack(padx=5, pady=10)
text_video_paths.tag_config("tag_1", foreground="green")
text_video_paths.tag_config("tag_2", foreground="blue")
text_video_paths.insert(tk.END, readme, "tag_1")
root.mainloop()
2024.09.23 更新:增加选框,可自定义填写导出码率

使用PyInstaller打包成exe文件
打包命令:
"C:\Users\...\横转竖视频\venv\Scripts\python.exe" -m PyInstaller --onefile -F "C:\Users\...\横转竖视频\横版视频改竖版1.1.py"
打包好的exe下载地址
https://wwmd.lanzouv.com/b03fkjyc5a
密码52pj