您的位置:首页 > 新闻 > 会展 > 甘肃兰州旅游必去十大景点_免费企业建站_营销中存在的问题及对策_哪个搜索引擎最好

甘肃兰州旅游必去十大景点_免费企业建站_营销中存在的问题及对策_哪个搜索引擎最好

2024/12/27 4:07:46 来源:https://blog.csdn.net/Clay_K/article/details/144246808  浏览:    关键词:甘肃兰州旅游必去十大景点_免费企业建站_营销中存在的问题及对策_哪个搜索引擎最好
甘肃兰州旅游必去十大景点_免费企业建站_营销中存在的问题及对策_哪个搜索引擎最好

Python 批量剪辑视频片头片尾工具

1.简介:

批量剪辑片头片尾的软件,让你的视频创作事半功倍,视频剪辑处理完成后,用户可以在指定文件夹中查看已经剪切完片头片尾的视频‌。这些工具不仅适用于个人用户进行日常的视频编辑工作,也适合视频制作团队在项目制作中提高工作效率。

功能:

  1. 加载和保存配置:读取和保存配置文件。
  2. 获取视频时长:使用ffprobe获取视频的总时长。
  3. 视频剪辑:使用ffmpeg截取视频片段,支持批量处理。
  4. 图形用户界面:通过tkinter选择输入文件和输出目录,设置开始和结束时间。
  5. 语音提示:在剪辑完成后进行语音提示。

2.运行效果:

在这里插入图片描述

3.相关源码:

import os
import subprocess
import threading
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk
import json
from datetime import datetime, timedelta
import pyttsx3INTERNAL_FOLDER = os.path.join(os.path.dirname(__file__), '_internal')
CONFIG_FILE = os.path.join(INTERNAL_FOLDER, 'config.json')
FFMPEG_FOLDER = os.path.join(INTERNAL_FOLDER, 'ffmpeg_folder')
COMPLETION_FILE = os.path.join(INTERNAL_FOLDER, 'completed.txt')
ICON_PATH = os.path.join(INTERNAL_FOLDER, 'moviecamera.ico')  # 使用_internal文件夹中的图标def ensure_internal_dir_exists():if not os.path.exists(INTERNAL_FOLDER):os.makedirs(INTERNAL_FOLDER)def load_config():if os.path.exists(CONFIG_FILE):with open(CONFIG_FILE, 'r', encoding='utf-8') as f:return json.load(f)return {}def save_config(config):ensure_internal_dir_exists()with open(CONFIG_FILE, 'w', encoding='utf-8') as f:json.dump(config, f)def format_time(hours, minutes, seconds, milliseconds):return f"{int(hours):02}:{int(minutes):02}:{int(seconds):02}.{int(milliseconds):03}"def get_video_duration(input_path):ffprobe_path = os.path.join(FFMPEG_FOLDER, 'ffprobe.exe')if not os.path.exists(ffprobe_path):messagebox.showerror("错误", "找不到 ffprobe 可执行文件")return 0result = subprocess.run([ffprobe_path, "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", input_path],stdout=subprocess.PIPE,stderr=subprocess.PIPE,universal_newlines=True)try:return float(result.stdout)except ValueError:print("FFprobe输出:", result.stdout)  # 打印ffprobe标准输出以便调试print("FFprobe错误:", result.stderr)  # 打印ffprobe错误输出以便调试messagebox.showerror("错误", "无法获取视频时长,请检查输入文件")return 0def trim_video(input_path, output_path, start_time, end_time):ffmpeg_path = os.path.join(FFMPEG_FOLDER, 'ffmpeg.exe')if not os.path.exists(ffmpeg_path):messagebox.showerror("错误", "找不到 ffmpeg 可执行文件")returnif start_time == "00:00:00.000" and end_time == "00:00:00.000":messagebox.showerror("错误", "请至少选择一个开始时间或结束时间")returnduration = get_video_duration(input_path)if duration == 0:returnstart_time_seconds = timedelta(hours=int(start_time.split(":")[0]),minutes=int(start_time.split(":")[1]),seconds=int(start_time.split(":")[2].split(".")[0]),milliseconds=int(start_time.split(":")[2].split(".")[1])).total_seconds()end_time_seconds = timedelta(hours=int(end_time.split(":")[0]),minutes=int(end_time.split(":")[1]),seconds=int(end_time.split(":")[2].split(".")[0]),milliseconds=int(end_time.split(":")[2].split(".")[1])).total_seconds()trim_duration = duration - start_time_seconds - end_time_secondsif trim_duration <= 0:messagebox.showerror("错误", "剪辑后的持续时间小于等于0")returncmd = [ffmpeg_path,'-ss', start_time,'-i', input_path,'-t', str(trim_duration),'-vcodec', 'copy','-acodec', 'copy',output_path,'-y']print("执行FFmpeg命令:", " ".join(cmd))  # 打印命令以便调试startupinfo = subprocess.STARTUPINFO()startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOWresult = subprocess.run(cmd, startupinfo=startupinfo, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, encoding='utf-8')print("FFmpeg输出:", result.stdout)  # 打印FFmpeg标准输出print("FFmpeg错误:", result.stderr)  # 打印FFmpeg错误输出if result.returncode != 0:messagebox.showerror("错误", f"FFmpeg执行失败: {result.stderr}")def batch_trim_videos(input_files, output_dir, start_time, end_time):if not os.path.exists(output_dir):os.makedirs(output_dir)for input_file in input_files:output_file = os.path.join(output_dir, os.path.basename(input_file))trim_video(input_file, output_file, start_time, end_time)with open(COMPLETION_FILE, 'w', encoding='utf-8') as f:f.write("老弟已经完成了,你开心吗")print("视频剪辑完成标志已写入文件")def select_input_files():files = filedialog.askopenfilenames(filetypes=[("MP4 files", "*.mp4")])if files:entry_input_files.delete(0, tk.END)entry_input_files.insert(0, f"已选择 {len(files)} 个文件")entry_input_files.files = filesdef select_output_directory():directory = filedialog.askdirectory()if directory:entry_output_directory.config(state='normal')entry_output_directory.delete(0, tk.END)entry_output_directory.insert(0, directory)entry_output_directory.config(state='disabled', disabledbackground='#d9d9d9', disabledforeground='#000000')label_status.config(text="输出目录已选择。请选择开始时间和结束时间。")config['output_directory'] = directorysave_config(config)def validate_time_format(time_str):try:datetime.strptime(time_str, '%H:%M:%S.%f')return Trueexcept ValueError:return Falsedef start_trimming():input_files = getattr(entry_input_files, 'files', [])output_directory = entry_output_directory.get()start_time = format_time(var_start_hours.get(), var_start_minutes.get(), var_start_seconds.get(), var_start_milliseconds.get())end_time = format_time(var_end_hours.get(), var_end_minutes.get(), var_end_seconds.get(), var_end_milliseconds.get())# 验证时间格式if not validate_time_format(start_time) or not validate_time_format(end_time):messagebox.showerror("错误", "时间格式不正确")returnif start_time == "00:00:00.000" and end_time == "00:00:00.000":messagebox.showerror("错误", "请至少选择一个开始时间或结束时间")returnif not input_files:messagebox.showwarning("警告", "请选择输入文件!")returnif not output_directory:messagebox.showwarning("警告", "请选择输出目录!")returnthreading.Thread(target=batch_trim_videos, args=(input_files, output_directory, start_time, end_time)).start()threading.Thread(target=monitor_completion).start()def monitor_completion():while not os.path.exists(COMPLETION_FILE):passwith open(COMPLETION_FILE, 'r', encoding='utf-8') as f:message = f.read()print("检测到完成标志文件,内容:", message)speak(message)def speak(text):print("初始化语音引擎")engine = pyttsx3.init()print("语音引擎初始化成功")engine.say(text)print("语音引擎开始说话")engine.runAndWait()print("语音引擎说话结束")def show_about():about_window = tk.Toplevel(root)about_window.title("关于")about_window.geometry("400x300")about_window.resizable(False, False)text = tk.Text(about_window, wrap='word', height=15, width=50)text.insert(tk.END, "n这是一个用来截取视频片段的小工具。\n\n功能特性:\n""1. 支持批量视频截取\n""2. 支持自定义开始时间和结束时间\n""3. 使用 FFmpeg 进行视频处理\n""4. 提供简单易用的图形用户界面\n\n""感谢使用本工具!(是无损快剪哈)")text.config(state='disabled')scrollbar = tk.Scrollbar(about_window, command=text.yview)text.config(yscrollcommand=scrollbar.set)text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)scrollbar.pack(side=tk.RIGHT, fill=tk.Y)config = load_config()root = tk.Tk()
root.title("视频截取工具")
root.geometry("510x250")
root.resizable(False, False)
root.iconbitmap(ICON_PATH)  # 设置窗口图标# 创建菜单栏
menu_bar = tk.Menu(root)
root.config(menu=menu_bar)# 创建菜单
menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="菜单", menu=menu)
menu.add_command(label="关于", command=show_about)tk.Label(root, text="选择输入文件:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
entry_input_files = tk.Entry(root, width=50)
entry_input_files.grid(row=0, column=1, padx=5, pady=5, columnspan=4, sticky='w')
entry_input_files.files = []
tk.Button(root, text="浏览", command=select_input_files).grid(row=0, column=5, padx=5, pady=5, sticky='w')tk.Label(root, text="选择输出目录:").grid(row=1, column=0, padx=5, pady=5, sticky='e')
entry_output_directory = tk.Entry(root, width=50)
entry_output_directory.grid(row=1, column=1, padx=5, pady=5, columnspan=4, sticky='w')
tk.Button(root, text="浏览", command=select_output_directory).grid(row=1, column=5, padx=5, pady=5, sticky='w')if 'output_directory' in config:entry_output_directory.insert(0, config['output_directory'])entry_output_directory.config(state='disabled', disabledbackground='#d9d9d9', disabledforeground='#000000')label_status = tk.Label(root, text="输出目录已选择。请选择开始时间和结束时间。")
else:label_status = tk.Label(root, text="请选择输出目录。")label_status.grid(row=4, column=0, columnspan=6, pady=10)hours = [f"{i:02}" for i in range(24)]
minutes_seconds = [f"{i:02}" for i in range(60)]
milliseconds = [f"{i:03}" for i in range(1000)]var_start_hours = tk.StringVar(value="00")
var_start_minutes = tk.StringVar(value="00")
var_start_seconds = tk.StringVar(value="00")
var_start_milliseconds = tk.StringVar(value="000")var_end_hours = tk.StringVar(value="00")
var_end_minutes = tk.StringVar(value="00")
var_end_seconds = tk.StringVar(value="00")
var_end_milliseconds = tk.StringVar(value="000")def create_time_frame(root, var_hours, var_minutes, var_seconds, var_milliseconds):frame = tk.Frame(root)ttk.Combobox(frame, textvariable=var_hours, values=hours, width=3).pack(side='left')tk.Label(frame, text="时").pack(side='left', padx=3)ttk.Combobox(frame, textvariable=var_minutes, values=minutes_seconds, width=3).pack(side='left')tk.Label(frame, text="分").pack(side='left', padx=3)ttk.Combobox(frame, textvariable=var_seconds, values=minutes_seconds, width=3).pack(side='left')tk.Label(frame, text="秒").pack(side='left', padx=3)ttk.Combobox(frame, textvariable=var_milliseconds, values=milliseconds, width=4).pack(side='left')tk.Label(frame, text="毫秒").pack(side='left', padx=3)return frametk.Label(root, text="开始时间:").grid(row=2, column=0, padx=5, pady=5, sticky='e')
start_time_frame = create_time_frame(root, var_start_hours, var_start_minutes, var_start_seconds, var_start_milliseconds)
start_time_frame.grid(row=2, column=1, columnspan=5, padx=5, pady=5, sticky='w')tk.Label(root, text="结束时间:").grid(row=3, column=0, padx=5, pady=5, sticky='e')
end_time_frame = create_time_frame(root, var_end_hours, var_end_minutes, var_end_seconds, var_end_milliseconds)
end_time_frame.grid(row=3, column=1, columnspan=5, padx=5, pady=5, sticky='w')tk.Button(root, text="开始截取", command=start_trimming).grid(row=5, column=0, columnspan=6, pady=10, sticky='ew')root.mainloop()

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com