Удалено скачивание видео (видео не сохраняется, кнопка убрана); исправлено перекрытие строк в PDF (ячейки-Paragraph + семейство шрифтов)
This commit is contained in:
1 parent
ce67122035
commit
25ed2e3899
3 files changed
+33
-71
No files matched your search
@@ -23,7 +23,7 @@ import time
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from flask import Flask, Response, jsonify, render_template, request, send_file
|
||||
from flask import Flask, Response, jsonify, render_template, request
|
||||
|
||||
# Импортируем модули интерпретации и хранения
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
@@ -94,16 +94,6 @@ os.makedirs(UPLOAD_DIR, exist_ok=True)
|
||||
VIDEO_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "videos")
|
||||
os.makedirs(VIDEO_DIR, exist_ok=True)
|
||||
|
||||
# MIME-типы для скачивания видео
|
||||
VIDEO_MIME = {
|
||||
".mp4": "video/mp4",
|
||||
".webm": "video/webm",
|
||||
".mov": "video/quicktime",
|
||||
".mkv": "video/x-matroska",
|
||||
".avi": "video/x-msvideo",
|
||||
".m4v": "video/mp4",
|
||||
}
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config["MAX_CONTENT_LENGTH"] = 100 * 1024 * 1024 # 100 МБ
|
||||
|
||||
@@ -412,12 +402,11 @@ def shared_result(share_id):
|
||||
"""Публичная страница результата по ссылке (с OG-тегами для соцсетей)."""
|
||||
result = storage.get_result(share_id)
|
||||
if result is None:
|
||||
return render_template("result.html", result=None, error="Результат не найден", video_exists=False, base_url=BASE_URL), 404
|
||||
return render_template("result.html", result=None, error="Результат не найден", base_url=BASE_URL), 404
|
||||
if storage.is_expired(result["created_at"]):
|
||||
return render_template("result.html", result=None, error="Ссылка устарела. Результат доступен в течение 30 минут после сканирования.", video_exists=False, base_url=BASE_URL), 410
|
||||
return render_template("result.html", result=None, error="Ссылка устарела. Результат доступен в течение 30 минут после сканирования.", base_url=BASE_URL), 410
|
||||
|
||||
video_exists = bool(glob.glob(os.path.join(VIDEO_DIR, f"{share_id}.*")))
|
||||
return render_template("result.html", result=result, error=None, video_exists=video_exists, base_url=BASE_URL)
|
||||
return render_template("result.html", result=result, error=None, base_url=BASE_URL)
|
||||
|
||||
|
||||
@app.route("/download/<share_id>/pdf")
|
||||
@@ -466,33 +455,6 @@ def download_docx(share_id):
|
||||
)
|
||||
|
||||
|
||||
@app.route("/download/<video_id>/video")
|
||||
def download_video(video_id):
|
||||
"""Скачать видео, записанное при сканировании (то, что было в кружке)."""
|
||||
# Если video_id соответствует результату в БД — проверяем срок действия.
|
||||
result = storage.get_result(video_id)
|
||||
if result is not None and storage.is_expired(result["created_at"]):
|
||||
return "Ссылка устарела. Результат доступен в течение 30 минут.", 410
|
||||
matches = glob.glob(os.path.join(VIDEO_DIR, f"{video_id}.*"))
|
||||
if not matches:
|
||||
return "Видео не найдено", 404
|
||||
video_path = matches[0]
|
||||
# Если результата в БД нет (неудачный анализ) — проверяем время создания файла.
|
||||
if result is None:
|
||||
mtime = datetime.fromtimestamp(os.path.getmtime(video_path))
|
||||
if datetime.now() - mtime > storage.RESULT_TTL:
|
||||
return "Ссылка устарела. Видео доступно в течение 30 минут.", 410
|
||||
video_path = matches[0]
|
||||
ext = os.path.splitext(video_path)[1].lower()
|
||||
mime = VIDEO_MIME.get(ext, "application/octet-stream")
|
||||
return send_file(
|
||||
video_path,
|
||||
mimetype=mime,
|
||||
as_attachment=True,
|
||||
download_name=f"scan_{video_id}{ext}",
|
||||
)
|
||||
|
||||
|
||||
@app.route("/analyze", methods=["POST", "OPTIONS"])
|
||||
def analyze():
|
||||
# Preflight-запрос CORS (браузер шлёт OPTIONS перед кросс-доменным POST)
|
||||
@@ -524,14 +486,6 @@ def analyze():
|
||||
logger.error(f"[{job_id}] Ошибка сохранения видео: {e}")
|
||||
return jsonify({"error": f"Не удалось сохранить видео: {e}"}), 500
|
||||
|
||||
# Сохраняем копию записанного видео (то, что было в кружке) — даже если анализ упадёт
|
||||
saved_video = os.path.join(VIDEO_DIR, f"{job_id}{ext}")
|
||||
try:
|
||||
shutil.copy2(video_path, saved_video)
|
||||
except Exception as e:
|
||||
logger.warning(f"[{job_id}] Не удалось сохранить видео: {e}")
|
||||
saved_video = None
|
||||
|
||||
token = None
|
||||
uid = None
|
||||
try:
|
||||
@@ -553,10 +507,8 @@ def analyze():
|
||||
result = asyncio.run(ws_stream(token, uid, frames))
|
||||
|
||||
if not result:
|
||||
video_url = f"/download/{job_id}/video" if saved_video else None
|
||||
return jsonify({
|
||||
"error": "Не удалось получить результат. Убедитесь, что на видео чётко видно лицо.",
|
||||
"video_url": video_url,
|
||||
}), 500
|
||||
|
||||
# 5. Интерпретация
|
||||
@@ -569,25 +521,14 @@ def analyze():
|
||||
share_url = f"{BASE_URL}/r/{share_id}"
|
||||
logger.info(f"[{job_id}] Результат сохранён: {share_url}")
|
||||
|
||||
# Переименовываем видео под share_id (чтобы ссылка была стабильной)
|
||||
if saved_video:
|
||||
final_video = os.path.join(VIDEO_DIR, f"{share_id}{ext}")
|
||||
try:
|
||||
os.rename(saved_video, final_video)
|
||||
saved_video = final_video
|
||||
except Exception as e:
|
||||
logger.warning(f"[{job_id}] Не удалось переименовать видео: {e}")
|
||||
|
||||
interpretation["share_id"] = share_id
|
||||
interpretation["share_url"] = share_url
|
||||
interpretation["video_url"] = f"/download/{share_id}/video" if saved_video else None
|
||||
|
||||
return jsonify(interpretation)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[{job_id}] Ошибка: {e}")
|
||||
video_url = f"/download/{job_id}/video" if saved_video else None
|
||||
return jsonify({"error": str(e), "video_url": video_url}), 500
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
finally:
|
||||
# 6. Удаление сессии
|
||||
|
||||
Reference in new issue
Block a user