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)}"