MPEGEndFrame / video_merger.py
dseditor's picture
Upload 3 files
fe72b7c verified
import subprocess
import os
import tempfile
def merge_videos(video_files):
"""
合併多個 MP4 影片檔案
Args:
video_files: 影片檔案路徑列表
Returns:
tuple: (輸出檔案路徑, 狀態訊息)
"""
if not video_files or len(video_files) == 0:
return None, "請至少上傳一個影片檔案"
if len(video_files) == 1:
return None, "請上傳至少兩個影片進行合併"
try:
# 創建臨時檔案列表
list_file = tempfile.mktemp(suffix='.txt')
output_path = tempfile.mktemp(suffix='.mp4')
# 寫入 ffmpeg concat 檔案列表
with open(list_file, 'w', encoding='utf-8') as f:
for video_file in video_files:
# 使用絕對路徑並轉義特殊字元
abs_path = os.path.abspath(video_file)
f.write(f"file '{abs_path}'\n")
# 使用 ffmpeg concat demuxer 合併影片
merge_cmd = [
'ffmpeg',
'-f', 'concat',
'-safe', '0',
'-i', list_file,
'-c', 'copy',
output_path,
'-y'
]
result = subprocess.run(merge_cmd, capture_output=True, text=True)
# 清理臨時列表檔案
if os.path.exists(list_file):
os.remove(list_file)
if result.returncode != 0:
# 如果直接複製失敗,嘗試重新編碼
merge_cmd_reencode = [
'ffmpeg',
'-f', 'concat',
'-safe', '0',
'-i', list_file,
'-c:v', 'libx264',
'-c:a', 'aac',
'-preset', 'medium',
output_path,
'-y'
]
# 重新創建列表檔案
with open(list_file, 'w', encoding='utf-8') as f:
for video_file in video_files:
abs_path = os.path.abspath(video_file)
f.write(f"file '{abs_path}'\n")
result = subprocess.run(merge_cmd_reencode, capture_output=True, text=True)
if os.path.exists(list_file):
os.remove(list_file)
if result.returncode != 0:
return None, f"合併失敗: {result.stderr}"
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
return output_path, f"成功合併 {len(video_files)} 個影片!"
else:
return None, "合併失敗,請確認影片格式正確"
except Exception as e:
return None, f"發生錯誤: {str(e)}"