File size: 5,322 Bytes
f1a7e59
 
 
92fd1a7
aebd124
da95709
92fd1a7
 
 
aebd124
92fd1a7
 
aebd124
92fd1a7
 
 
 
aebd124
92fd1a7
 
 
 
 
 
aebd124
92fd1a7
 
 
aebd124
92fd1a7
 
 
 
aebd124
92fd1a7
 
37e59a0
aebd124
92fd1a7
 
 
aebd124
92fd1a7
 
aebd124
f1a7e59
aebd124
92fd1a7
aebd124
92fd1a7
f1a7e59
aebd124
92fd1a7
 
aebd124
f1a7e59
aebd124
f1a7e59
92fd1a7
 
f1a7e59
 
 
 
 
 
 
 
 
d369cf2
 
f1a7e59
 
d369cf2
 
 
 
 
94a2fe4
 
 
 
 
 
 
 
 
 
f1a7e59
92fd1a7
f1a7e59
 
 
94a2fe4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92fd1a7
aebd124
57c92c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
be8d0ca
 
94a2fe4
92fd1a7
 
 
aebd124
92fd1a7
 
 
f1a7e59
92fd1a7
f1a7e59
 
 
aebd124
92fd1a7
 
 
 
aebd124
92fd1a7
 
 
aebd124
92fd1a7
 
 
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
"""FastAPI API-only application with DDD architecture."""
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
from contextlib import asynccontextmanager
import logging

# Infrastructure imports
from infrastructure.config.settings import settings
from infrastructure.services.container import ServiceContainer

# Application imports
from application.use_cases.container import UseCaseContainer

# Interface imports
from interfaces.api.routes import register_routes
from interfaces.api.middleware.error_handler import register_exception_handlers
from interfaces.api.middleware.cors_middleware import configure_cors

# Configure logging
logging.basicConfig(
    level=logging.INFO if not settings.debug else logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# Global containers
service_container: ServiceContainer = None
use_case_container: UseCaseContainer = None

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan manager."""
    global service_container, use_case_container
    
    # Startup
    logger.info(f"Starting {settings.app_name} v{settings.app_version}")
    logger.info(f"Storage type: {settings.storage_type}")
    
    # Initialize containers
    service_container = ServiceContainer.get_instance()
    use_case_container = UseCaseContainer(service_container, settings)
    
    # Start background services
    await service_container.startup()
    
    logger.info("API service started successfully")
    
    yield
    
    # Shutdown
    logger.info("Shutting down API service")
    
    # Stop background services
    await service_container.shutdown()
    
    logger.info("API service shut down successfully")

# Create FastAPI app with API documentation
app = FastAPI(
    title=settings.app_name,
    description="""
    ## Audio Extraction API
    
    Extract audio from video files in various formats with customizable quality settings.
    
    ### Features
    - πŸŽ₯ Support for multiple video formats (MP4, AVI, MOV, MKV, WebM, etc.)
    - 🎡 Multiple audio output formats (MP3, AAC, WAV, FLAC, M4A, OGG)
    - πŸ“Š Three quality levels (High, Medium, Low)
    - πŸš€ Asynchronous processing for all files
    - βœ‚οΈ Audio trimming with start/end time parameters
    
    ### Processing Flow
    1. **Upload video**: POST to `/extract` endpoint
    2. **Get job ID**: Immediate response with job tracking information
    3. **Check status**: Monitor progress with `/jobs/{job_id}`
    4. **Download result**: Get extracted audio with `/jobs/{job_id}/download`
    5. **Optional trimming**: Use `start` and `end` parameters to download specific segments
    
    ### Authentication
    Most endpoints require JWT Bearer token authentication. Include your token in the Authorization header:
    ```
    Authorization: Bearer <your-jwt-token>
    ```
    
    Public endpoints (no authentication required):
    - `GET /api/v1/info` - API information
    - `GET /api/v1/health` - Health check
    """,
    version=settings.app_version,
    docs_url="/docs",
    redoc_url="/redoc",
    openapi_url="/openapi.json",
    lifespan=lifespan,
    # Add OpenAPI security scheme for Bearer token authentication
    openapi_tags=[
        {
            "name": "extraction",
            "description": "Audio extraction operations (requires authentication)"
        },
        {
            "name": "jobs", 
            "description": "Job management operations (requires authentication)"
        },
        {
            "name": "info",
            "description": "Public API information (no authentication required)"
        }
    ]
)

# Configure OpenAPI security scheme
def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema
    
    from fastapi.openapi.utils import get_openapi
    
    openapi_schema = get_openapi(
        title=app.title,
        version=app.version,
        description=app.description,
        routes=app.routes,
    )
    
    # Add Bearer token security scheme
    openapi_schema["components"]["securitySchemes"] = {
        "BearerAuth": {
            "type": "http",
            "scheme": "bearer",
            "bearerFormat": "JWT",
            "description": "JWT Bearer token authentication"
        }
    }
    
    app.openapi_schema = openapi_schema
    return app.openapi_schema

app.openapi = custom_openapi

# Let FastAPI handle OpenAPI generation automatically
# The HTTPBearer scheme in dependencies.py will be automatically detected

# Configure middleware
configure_cors(app)
register_exception_handlers(app)

# Register API routes
register_routes(app)

# Root redirect to documentation
@app.get("/", include_in_schema=False)
async def root():
    """Redirect root to API documentation."""
    return RedirectResponse(url="/docs")

# Dependency injection functions for routes
def get_service_container() -> ServiceContainer:
    """Get service container for dependency injection."""
    return service_container

def get_use_case_container() -> UseCaseContainer:
    """Get use case container for dependency injection."""
    return use_case_container

# Make containers available for dependency injection
app.state.get_services = get_service_container
app.state.get_use_cases = get_use_case_container