import streamlit as st from pathlib import Path import tempfile, subprocess, threading, queue import textwrap import streamlit.components.v1 as components st.set_page_config(page_title="Lec2Note2 – Lecture-to-Notes", layout="wide") st.title("📝 Lec2Note – Automatic Lecture Notes Generator") # Inject MathJax once for LaTeX rendering MATHJAX = "" components.html(MATHJAX, height=0) st.markdown( textwrap.dedent( """ Upload a lecture **video** and receive a fully-formatted **Markdown** study note – complete with key images and structured sections. The processing pipeline performs ASR transcription, vision & semantic segmentation, then invokes an LLM to produce rich notes. """ ) ) video_file = st.file_uploader("🎬 Upload MP4/MKV/AVI", type=["mp4", "mkv", "avi"]) run_btn = st.button("🚀 Generate Notes", disabled=video_file is None) if run_btn and video_file: # Save upload to a temporary file tmp_dir = tempfile.TemporaryDirectory() vid_path = Path(tmp_dir.name) / video_file.name with vid_path.open("wb") as f: f.write(video_file.read()) output_md = vid_path.with_suffix(".md") st.info("Processing started. This may take several minutes depending on video length …") # container for live log streaming log_container = st.container() log_placeholder = log_container.code("", language="bash", height=300) # Run pipeline via subprocess to avoid blocking UI; capture logs with st.spinner("Running Lec2Note2 pipeline …"): # launch pipeline in subprocess with unbuffered output cmd = [ "python", "-u", # unbuffer stdout "-m", "lec2note.scripts.run_pipeline", "--video", str(vid_path), "--output", str(output_md), ] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) log_queue: "queue.Queue[str]" = queue.Queue() def _enqueue_output(pipe, q): for line in iter(pipe.readline, ""): q.put(line) pipe.close() threading.Thread(target=_enqueue_output, args=(proc.stdout, log_queue), daemon=True).start() logs = "" line_count = 0 while True: try: line = log_queue.get(timeout=0.1) except queue.Empty: if proc.poll() is not None: # process finished and queue empty break continue logs += line line_count += 1 if line_count % 5 == 0: # update UI every 5 lines to reduce overhead log_placeholder.code(logs, language="bash", height=300) # final flush log_placeholder.code(logs, language="bash", height=300) result_code = proc.wait() if result_code != 0: st.error("❌ Pipeline failed. See logs below.") with st.expander("Show logs"): st.code(logs) else: st.success("✅ Notes generated!") md_content = output_md.read_text() with st.container(border=True): st.markdown(md_content, unsafe_allow_html=True) st.download_button( label="💾 Download notes.md", data=md_content, file_name="lecture_notes.md", mime="text/markdown", ) tmp_dir.cleanup()