Spaces:
Sleeping
Sleeping
File size: 4,544 Bytes
ebb2801 0616ade ebb2801 0616ade ebb2801 0616ade 23b4a3c 0616ade 23b4a3c 0616ade 23b4a3c 0616ade ebb2801 0616ade ebb2801 c4aaa51 0616ade c4aaa51 0616ade 23b4a3c 0616ade 23b4a3c 0616ade 23b4a3c c4aaa51 0616ade c4aaa51 0616ade c4aaa51 0616ade c4aaa51 0616ade c4aaa51 ebb2801 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
from flask import Flask, render_template, request, jsonify, send_file
from werkzeug.exceptions import HTTPException
import os
import subprocess
import uuid
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['OUTPUT_FOLDER'] = 'outputs'
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024 # 100MB limit to prevent server overload
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
os.makedirs(app.config['OUTPUT_FOLDER'], exist_ok=True)
import shutil
import time
import traceback
# Check if ffmpeg is installed
FFMPEG_AVAILABLE = shutil.which('ffmpeg') is not None
def cleanup_old_files():
"""Cleanup files older than 1 hour"""
try:
now = time.time()
for folder in [app.config['UPLOAD_FOLDER'], app.config['OUTPUT_FOLDER']]:
if not os.path.exists(folder):
continue
for filename in os.listdir(folder):
filepath = os.path.join(folder, filename)
# Remove if older than 1 hour
if os.path.isfile(filepath) and os.path.getmtime(filepath) < now - 3600:
try:
os.remove(filepath)
except Exception:
pass
except Exception:
pass
@app.errorhandler(500)
def internal_error(error):
return jsonify({
"error": "服务器内部错误 (Internal Server Error)",
"details": str(error),
"trace": traceback.format_exc(),
"suggestion": "请尝试上传较小的文件,或检查文件格式是否正确。"
}), 500
@app.errorhandler(413)
def request_entity_too_large(error):
return jsonify({
"error": "文件过大 (File Too Large)",
"details": "上传的文件超过了服务器限制 (100MB)。"
}), 413
@app.errorhandler(Exception)
def handle_exception(e):
# Pass through HTTP errors
if isinstance(e, HTTPException):
return e
# Log the full traceback
print("Error occurred:")
traceback.print_exc()
# Now you're handling non-HTTP exceptions only
return jsonify({
"error": "Unexpected Error",
"details": str(e),
"trace": traceback.format_exc() # Return trace to client for debugging
}), 500
@app.route('/')
def index():
return render_template('index.html', ffmpeg_available=FFMPEG_AVAILABLE)
@app.route('/convert', methods=['POST'])
def convert():
cleanup_old_files()
if 'video' not in request.files:
return jsonify({"error": "No video file"}), 400
video = request.files['video']
filename = str(uuid.uuid4())
input_path = os.path.join(app.config['UPLOAD_FOLDER'], filename + '.webm')
output_path = os.path.join(app.config['OUTPUT_FOLDER'], filename + '.mp4')
try:
video.save(input_path)
if not FFMPEG_AVAILABLE:
return jsonify({"error": "FFmpeg not installed on server", "fallback": True}), 503
# FFmpeg conversion
# -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" ensures dimensions are even for libx264
# -pix_fmt yuv420p is often required for broad compatibility
# Added -movflags +faststart for better web playback
cmd = [
'ffmpeg', '-y', '-i', input_path,
'-c:v', 'libx264', '-preset', 'fast', '-crf', '23',
'-pix_fmt', 'yuv420p',
'-c:a', 'aac', '-b:a', '192k',
'-vf', 'pad=ceil(iw/2)*2:ceil(ih/2)*2',
'-movflags', '+faststart',
output_path
]
# Log command for debugging
print(f"Running command: {' '.join(cmd)}")
subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return jsonify({"url": f"/download/{filename}.mp4"})
except subprocess.CalledProcessError as e:
print(f"FFmpeg Error: {e.stderr.decode() if e.stderr else str(e)}")
return jsonify({"error": "Conversion failed", "details": str(e)}), 500
except Exception as e:
print(f"General Error: {str(e)}")
return jsonify({"error": "Internal server error", "details": str(e)}), 500
finally:
# Cleanup input
if os.path.exists(input_path):
try:
os.remove(input_path)
except:
pass
@app.route('/download/<filename>')
def download_file(filename):
return send_file(os.path.join(app.config['OUTPUT_FOLDER'], filename), as_attachment=True)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860)
|