File size: 4,304 Bytes
706cf87
 
 
 
 
 
 
698ad13
706cf87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
698ad13
 
 
 
 
706cf87
 
 
 
 
 
 
698ad13
706cf87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Main entry point for YouTube Study Notes AI.
Provides CLI interface and server startup.
"""

import sys
import argparse
import os
from pathlib import Path

# Import necessary modules for server and middleware
from src.utils.logger import setup_logger
from src.utils.config import settings

logger = setup_logger(__name__)


def run_server():
    """Start the FastAPI server with CORS enabled for Flutter Web."""
    import uvicorn
    from fastapi.middleware.cors import CORSMiddleware
    from src.api.main import app  # Import the app instance directly

    logger.info("Configuring CORS for Flutter Web...")

    # Add CORS Middleware to allow requests from Chrome/Flutter
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],  # Allows all origins
        allow_credentials=True,
        allow_methods=["*"],  # Allows all methods
        allow_headers=["*"],  # Allows all headers
    )

    # ---------------------------------------------------------
    # TWEAK FOR HUGGING FACE SPACES
    # Hugging Face sets the 'PORT' environment variable to 7860.
    # We use it if available, otherwise fallback to 7860 default.
    # ---------------------------------------------------------
    port = int(os.environ.get("PORT", 7860))

    logger.info("Starting YouTube Study Notes AI server...")
    logger.info(f"Server will be available at http://0.0.0.0:{port}")
    logger.info(f"API Documentation: http://0.0.0.0:{port}/docs")

    # Run the server using the app object directly
    # Host must be "0.0.0.0" to be accessible externally
    uvicorn.run(app, host="0.0.0.0", port=port, log_level="info")


def run_cli(youtube_url: str, output_file: str = None):
    """
    Run note generation from command line.
    """
    from src.audio.downloader import YouTubeDownloader
    from src.transcription.whisper_transcriber import WhisperTranscriber
    from src.summarization.note_generator import NoteGenerator

    logger.info("Starting CLI mode")
    logger.info(f"Processing URL: {youtube_url}")

    try:
        # Step 1: Download audio
        logger.info("Step 1/3: Downloading audio...")
        downloader = YouTubeDownloader()
        video_info = downloader.get_video_info(youtube_url)
        audio_file = downloader.download_audio(youtube_url)

        # Step 2: Transcribe
        logger.info("Step 2/3: Transcribing audio...")
        transcriber = WhisperTranscriber()
        transcript_data = transcriber.transcribe(audio_file)

        # Step 3: Generate notes
        logger.info("Step 3/3: Generating notes...")
        note_gen = NoteGenerator()
        notes = note_gen.generate_notes_from_full_transcript(
            transcript_data["text"], video_info["title"]
        )

        # Format and save
        final_notes = note_gen.format_final_notes(
            notes, video_info["title"], youtube_url, video_info["duration"]
        )

        if output_file:
            output_path = Path(output_file)
        else:
            output_path = settings.output_dir / f"{video_info['title'][:50]}_notes.md"

        output_path.write_text(final_notes, encoding="utf-8")

        logger.info(f"✅ Notes saved to: {output_path}")
        print(f"\n✅ Success! Notes saved to: {output_path}")

        # Cleanup
        downloader.cleanup(audio_file)

    except Exception as e:
        logger.error(f"Failed: {e}")
        print(f"\n❌ Error: {e}")
        sys.exit(1)


def main():
    """Main entry point with argument parsing."""
    parser = argparse.ArgumentParser(
        description="YouTube Study Notes AI - Generate structured notes from educational videos"
    )

    parser.add_argument(
        "mode",
        choices=["server", "cli"],
        help="Run mode: server (API + web UI) or cli (direct processing)",
    )

    parser.add_argument(
        "--url", type=str, help="YouTube video URL (required for cli mode)"
    )

    parser.add_argument(
        "--output", type=str, help="Output file path (optional for cli mode)"
    )

    args = parser.parse_args()

    if args.mode == "server":
        run_server()
    elif args.mode == "cli":
        if not args.url:
            print("Error: --url is required for cli mode")
            sys.exit(1)
        run_cli(args.url, args.output)


if __name__ == "__main__":
    main()