| 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") |
|
|
| |
| MATHJAX = "<script src='https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js'></script>" |
| 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: |
| |
| 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 β¦") |
| |
| log_container = st.container() |
| log_placeholder = log_container.code("", language="bash", height=300) |
|
|
| |
| with st.spinner("Running Lec2Note2 pipeline β¦"): |
| |
| cmd = [ |
| "python", |
| "-u", |
| "-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: |
| |
| break |
| continue |
| logs += line |
| line_count += 1 |
| if line_count % 5 == 0: |
| log_placeholder.code(logs, language="bash", height=300) |
|
|
| |
| 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() |
|
|