File size: 6,225 Bytes
8e80ab9 77308ac 8e80ab9 87680ff 6b0d066 3ec06be dd0209f 8e80ab9 d465483 8e80ab9 f01b5cc 8e80ab9 f01b5cc 8e80ab9 d465483 dd0209f 8e80ab9 dd0209f d465483 dd0209f 8e80ab9 77308ac dd0209f d465483 dd0209f d465483 3ec06be 8e80ab9 d465483 77308ac d465483 87680ff db66357 2b0c920 db66357 2b0c920 db66357 2b0c920 db66357 602f352 db66357 5fe7c80 2b0c920 5685865 dd0209f 77308ac db66357 dd0209f db66357 dd0209f d465483 f642dbf 8e80ab9 77308ac 6337f3a 77308ac 8e80ab9 f642dbf 8e80ab9 6337f3a f642dbf 3074b94 d465483 3074b94 571da76 d465483 8e80ab9 6337f3a f642dbf d465483 8e80ab9 6337f3a f642dbf 8e80ab9 f642dbf 8e80ab9 f642dbf 8e80ab9 d465483 8e80ab9 6337f3a d465483 87680ff 8e80ab9 d465483 d838606 |
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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
#!/usr/bin/env python3
"""
Advanced Video Background Replacer - Streamlit Entrypoint
"""
import os
import sys
import time
from pathlib import Path
import logging
import logging.handlers
import traceback
import uuid
from tempfile import NamedTemporaryFile
import streamlit as st
from ui import render_ui
from pipeline.video_pipeline import (
stage1_create_transparent_video,
stage2_composite_background,
setup_t4_environment,
check_gpu
)
from models.model_loaders import load_sam2, load_matanyone
APP_NAME = "Advanced Video Background Replacer"
LOG_FILE = "/tmp/app.log"
LOG_MAX_BYTES = 5 * 1024 * 1024
LOG_BACKUPS = 5
def setup_logging(level: int = logging.INFO) -> logging.Logger:
logger = logging.getLogger(APP_NAME)
logger.setLevel(level)
logger.propagate = False
# Remove previous handlers (Streamlit reruns)
for h in list(logger.handlers):
logger.removeHandler(h)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(level)
ch.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
fh = logging.handlers.RotatingFileHandler(
LOG_FILE, maxBytes=LOG_MAX_BYTES, backupCount=LOG_BACKUPS, encoding="utf-8"
)
fh.setLevel(level)
fh.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logger.addHandler(ch)
logger.addHandler(fh)
return logger
logger = setup_logging()
def custom_excepthook(type, value, tb):
logger.error(f"Unhandled: {type.__name__}: {value}\n{''.join(traceback.format_tb(tb))}", exc_info=True)
sys.excepthook = custom_excepthook
# Only load once
sam2_predictor = load_sam2()
matanyone_processor = load_matanyone()
def initialize_session_state():
defaults = {
'uploaded_video': None,
'video_bytes_cache': None,
'video_preview_placeholder': None,
'bg_image_cache': None,
'bg_preview_placeholder': None,
'bg_color': "#00FF00",
'cached_color': None,
'color_display_cache': None,
'processed_video_bytes': None,
'processing': False,
'gpu_available': None,
'last_video_id': None,
'last_bg_image_id': None,
'last_error': None,
'log_level_name': 'INFO',
'auto_refresh_logs': False,
'log_tail_lines': 400,
'generated_bg': None,
}
for k, v in defaults.items():
if k not in st.session_state:
st.session_state[k] = v
if st.session_state.gpu_available is None:
st.session_state.gpu_available = check_gpu(logger)
def process_video(uploaded_video, background, bg_type, progress_callback=None):
run_id = uuid.uuid4().hex[:8]
logger.info("=" * 80)
logger.info(f"[RUN {run_id}] VIDEO PROCESSING STARTED at {time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}")
logger.info(f"[RUN {run_id}] Video size={len(uploaded_video.read()) / 1e6:.2f}MB, BG type={bg_type}")
uploaded_video.seek(0)
st.session_state.processing = True
st.session_state.processed_video_bytes = None
st.session_state.last_error = None
t0 = time.time()
try:
if progress_callback:
progress_callback("π₯ Uploading video...")
suffix = Path(uploaded_video.name).suffix or ".mp4"
with NamedTemporaryFile(delete=False, suffix=suffix) as tmp_vid:
uploaded_video.seek(0)
tmp_vid.write(uploaded_video.read())
tmp_vid_path = tmp_vid.name
logger.info(f"[RUN {run_id}] Temporary video path: {tmp_vid_path}")
if progress_callback:
progress_callback("π Stage 1: Creating transparent video (matting & segmentation)...")
# >>> CHANGE: pass a short watchdog timeout so hangs surface quickly
transparent_path, audio_path = stage1_create_transparent_video(
tmp_vid_path,
sam2_predictor=sam2_predictor,
matanyone_processor=matanyone_processor,
mat_timeout_sec=300
)
if not transparent_path or not os.path.exists(transparent_path):
raise RuntimeError("Stage 1 failed: Transparent video not created")
logger.info(f"[RUN {run_id}] Stage 1 completed: Transparent path={transparent_path}, Audio path={audio_path}")
if progress_callback:
progress_callback("π¨ Stage 2: Compositing with background and restoring audio...")
final_path = stage2_composite_background(
transparent_path,
audio_path,
background,
bg_type.lower()
)
if not final_path or not os.path.exists(final_path):
raise RuntimeError("Stage 2 failed: Final video not created")
logger.info(f"[RUN {run_id}] Stage 2 completed: Final path={final_path}")
if progress_callback:
progress_callback("π€ Loading final video for download...")
with open(final_path, 'rb') as f:
st.session_state.processed_video_bytes = f.read()
total = time.time() - t0
logger.info(f"[RUN {run_id}] SUCCESS size={len(st.session_state.processed_video_bytes)/1e6:.2f}MB, total Ξ={total:.2f}s")
if progress_callback:
progress_callback("β
All done!")
return True
except Exception as e:
total = time.time() - t0
error_msg = f"[RUN {run_id}] Processing Error: {str(e)} (Ξ {total:.2f}s)\n\nCheck logs for details."
logger.error(error_msg)
logger.error(traceback.format_exc())
st.session_state.last_error = error_msg
if progress_callback:
progress_callback(f"β ERROR: {str(e)}")
return False
finally:
st.session_state.processing = False
logger.info(f"[RUN {run_id}] Processing finished")
def main():
try:
st.set_page_config(
page_title=APP_NAME,
page_icon="π₯",
layout="wide",
initial_sidebar_state="expanded"
)
initialize_session_state()
render_ui(process_video)
except Exception as e:
logger.error(f"Main app error: {e}", exc_info=True)
st.error(f"App startup failed: {str(e)}. Check logs for details.")
if __name__ == "__main__":
setup_t4_environment()
main()
|