Spaces:
Build error
Build error
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>TranscriptAI | YouTube Analysis Tool</title> | |
<!-- Bootstrap CSS --> | |
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> | |
<!-- Font Awesome --> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> | |
<!-- Google Fonts --> | |
<link rel="preconnect" href="https://fonts.googleapis.com"> | |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet"> | |
<style> | |
:root { | |
--primary: #4361ee; | |
--primary-dark: #3a56d4; | |
--secondary: #3f37c9; | |
--accent: #f72585; | |
--accent-light: #ff8fa3; | |
--success: #4cc9f0; | |
--warning: #f8961e; | |
--danger: #f94144; | |
--light: #f8f9fa; | |
--dark: #212529; | |
--gray-100: #f8f9fa; | |
--gray-200: #e9ecef; | |
--gray-300: #dee2e6; | |
--gray-400: #ced4da; | |
--gray-500: #adb5bd; | |
--gray-600: #6c757d; | |
--gray-700: #495057; | |
--gray-800: #343a40; | |
--gray-900: #212529; | |
} | |
body { | |
font-family: 'Inter', sans-serif; | |
background-color: #f7f9fc; | |
color: var(--gray-800); | |
line-height: 1.6; | |
} | |
h1, h2, h3, h4, h5, h6, .display-1, .display-2, .display-3, .display-4, .display-5, .display-6 { | |
font-family: 'Poppins', sans-serif; | |
font-weight: 600; | |
} | |
.navbar-brand { | |
font-family: 'Poppins', sans-serif; | |
font-weight: 700; | |
} | |
.card { | |
border-radius: 12px; | |
border: none; | |
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.08); | |
transition: transform 0.2s, box-shadow 0.2s; | |
} | |
.card:hover { | |
transform: translateY(-3px); | |
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); | |
} | |
.card-header { | |
background-color: #fff; | |
border-bottom: 1px solid var(--gray-200); | |
font-weight: 600; | |
padding: 1.25rem 1.5rem; | |
} | |
.card-body { | |
padding: 1.5rem; | |
} | |
.btn { | |
border-radius: 8px; | |
font-weight: 500; | |
padding: 0.6rem 1.2rem; | |
transition: all 0.2s; | |
} | |
.btn-primary { | |
background-color: var(--primary); | |
border-color: var(--primary); | |
} | |
.btn-primary:hover { | |
background-color: var(--primary-dark); | |
border-color: var(--primary-dark); | |
} | |
.btn-outline-primary { | |
color: var(--primary); | |
border-color: var(--primary); | |
} | |
.btn-outline-primary:hover { | |
background-color: var(--primary); | |
border-color: var(--primary); | |
} | |
.btn-success { | |
background-color: var(--success); | |
border-color: var(--success); | |
} | |
.form-control { | |
border-radius: 8px; | |
padding: 0.75rem 1rem; | |
border: 1px solid var(--gray-300); | |
font-size: 1rem; | |
} | |
.form-control:focus { | |
box-shadow: 0 0 0 0.25rem rgba(67, 97, 238, 0.15); | |
border-color: var(--primary); | |
} | |
.form-label { | |
font-weight: 500; | |
margin-bottom: 0.5rem; | |
color: var(--gray-700); | |
} | |
.form-text { | |
color: var(--gray-600); | |
} | |
.loading-overlay { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(15, 23, 42, 0.8); | |
backdrop-filter: blur(8px); | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
align-items: center; | |
z-index: 1050; | |
color: white; | |
display: none; | |
} | |
.progress-container { | |
width: 80%; | |
max-width: 600px; | |
margin-top: 20px; | |
} | |
.progress { | |
height: 10px; | |
border-radius: 10px; | |
background-color: rgba(255, 255, 255, 0.2); | |
overflow: hidden; | |
} | |
.progress-bar { | |
background-image: linear-gradient(to right, var(--primary), var(--accent)); | |
height: 100%; | |
border-radius: 10px; | |
} | |
.log-container { | |
width: 80%; | |
max-width: 600px; | |
height: 200px; | |
overflow-y: auto; | |
background-color: rgba(15, 23, 42, 0.5); | |
border-radius: 12px; | |
padding: 15px; | |
margin-top: 20px; | |
font-family: 'Courier New', monospace; | |
color: #e2e8f0; | |
border: 1px solid rgba(255, 255, 255, 0.1); | |
} | |
.log-container div { | |
padding: 3px 0; | |
border-bottom: 1px solid rgba(255, 255, 255, 0.05); | |
} | |
.log-container div:last-child { | |
border-bottom: none; | |
} | |
.logo { | |
font-size: 2.5rem; | |
background: linear-gradient(135deg, #f72585 0%, #4361ee 100%); | |
-webkit-background-clip: text; | |
-webkit-text-fill-color: transparent; | |
margin-right: 15px; | |
} | |
.nav-tabs { | |
border-bottom: none; | |
margin-bottom: 20px; | |
gap: 10px; | |
} | |
.nav-tabs .nav-item { | |
margin-bottom: 0; | |
} | |
.nav-tabs .nav-link { | |
border: none; | |
border-radius: 8px; | |
padding: 0.75rem 1.5rem; | |
color: var(--gray-600); | |
font-weight: 500; | |
transition: all 0.2s; | |
display: flex; | |
align-items: center; | |
gap: 8px; | |
} | |
.nav-tabs .nav-link:hover { | |
color: var(--primary); | |
background-color: rgba(67, 97, 238, 0.05); | |
} | |
.nav-tabs .nav-link.active { | |
color: var(--primary); | |
background-color: rgba(67, 97, 238, 0.1); | |
border-bottom: none; | |
font-weight: 600; | |
} | |
.nav-tabs .nav-link.active i { | |
color: var(--primary); | |
} | |
.tab-content { | |
background-color: #fff; | |
border-radius: 12px; | |
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.08); | |
padding: 0; | |
border: none; | |
} | |
.recent-items { | |
max-height: 500px; | |
overflow-y: auto; | |
} | |
#preview-container { | |
max-height: 700px; | |
overflow-y: auto; | |
padding: 25px; | |
border-radius: 12px; | |
background-color: #fff; | |
font-family: 'Inter', sans-serif; | |
line-height: 1.7; | |
} | |
#preview-container h1, #preview-container h2 { | |
font-weight: 700; | |
color: var(--gray-800); | |
margin-top: 1.5em; | |
margin-bottom: 0.75em; | |
} | |
#preview-container h1 { | |
font-size: 2rem; | |
border-bottom: 2px solid var(--gray-200); | |
padding-bottom: 0.5rem; | |
} | |
#preview-container h2 { | |
font-size: 1.5rem; | |
color: var(--primary); | |
} | |
#preview-container p { | |
margin-bottom: 1rem; | |
} | |
#preview-container ul, #preview-container ol { | |
padding-left: 1.5rem; | |
margin-bottom: 1rem; | |
} | |
#preview-container blockquote { | |
border-left: 4px solid var(--primary); | |
padding-left: 1rem; | |
margin-left: 0; | |
color: var(--gray-700); | |
font-style: italic; | |
} | |
.table th { | |
background-color: rgba(67, 97, 238, 0.05); | |
color: var(--gray-700); | |
font-weight: 600; | |
} | |
.table-hover tbody tr:hover { | |
background-color: rgba(67, 97, 238, 0.05); | |
} | |
.badge { | |
padding: 0.4em 0.8em; | |
font-weight: 500; | |
border-radius: 6px; | |
} | |
.badge-hindi { | |
background-color: rgba(247, 37, 133, 0.1); | |
color: var(--accent); | |
} | |
.badge-english { | |
background-color: rgba(67, 97, 238, 0.1); | |
color: var(--primary); | |
} | |
.btn-action { | |
padding: 0.4rem 0.75rem; | |
border-radius: 6px; | |
font-size: 0.875rem; | |
display: inline-flex; | |
align-items: center; | |
gap: 5px; | |
} | |
.btn-icon { | |
width: 36px; | |
height: 36px; | |
padding: 0; | |
display: inline-flex; | |
align-items: center; | |
justify-content: center; | |
border-radius: 50%; | |
} | |
.features-icon { | |
width: 40px; | |
height: 40px; | |
background-color: rgba(67, 97, 238, 0.1); | |
color: var(--primary); | |
border-radius: 12px; | |
display: inline-flex; | |
align-items: center; | |
justify-content: center; | |
margin-right: 15px; | |
font-size: 1.25rem; | |
} | |
.feature-item { | |
display: flex; | |
align-items: flex-start; | |
margin-bottom: 1rem; | |
} | |
.feature-content { | |
flex: 1; | |
} | |
.feature-content h5 { | |
margin-bottom: 0.25rem; | |
font-weight: 600; | |
} | |
.help-card { | |
height: 100%; | |
display: flex; | |
flex-direction: column; | |
} | |
.help-card .card-body { | |
flex: 1; | |
} | |
.banner { | |
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); | |
color: white; | |
padding: 2rem 0; | |
border-radius: 16px; | |
margin-bottom: 2rem; | |
} | |
.banner h2 { | |
font-weight: 700; | |
margin-bottom: 1rem; | |
} | |
.banner p { | |
opacity: 0.9; | |
font-weight: 300; | |
font-size: 1.1rem; | |
max-width: 600px; | |
} | |
@keyframes pulse { | |
0% { | |
transform: scale(1); | |
} | |
50% { | |
transform: scale(1.05); | |
} | |
100% { | |
transform: scale(1); | |
} | |
} | |
.pulse-icon { | |
animation: pulse 1.5s infinite; | |
} | |
/* For mobile screens */ | |
@media (max-width: 767.98px) { | |
.banner { | |
text-align: center; | |
padding: 1.5rem; | |
} | |
.banner p { | |
margin-left: auto; | |
margin-right: auto; | |
} | |
.nav-tabs { | |
overflow-x: auto; | |
flex-wrap: nowrap; | |
padding-bottom: 5px; | |
} | |
.nav-tabs .nav-link { | |
white-space: nowrap; | |
padding: 0.5rem 1rem; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<!-- Navbar --> | |
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm"> | |
<div class="container"> | |
<a class="navbar-brand d-flex align-items-center" href="/"> | |
<i class="fab fa-youtube logo"></i> | |
<span>TranscriptAI</span> | |
</a> | |
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> | |
<span class="navbar-toggler-icon"></span> | |
</button> | |
<div class="collapse navbar-collapse" id="navbarNav"> | |
<ul class="navbar-nav ms-auto"> | |
<li class="nav-item"> | |
<a class="nav-link active" href="#"><i class="fas fa-home me-1"></i> Home</a> | |
</li> | |
<li class="nav-item"> | |
<a class="nav-link" href="#"><i class="fas fa-info-circle me-1"></i> About</a> | |
</li> | |
<li class="nav-item"> | |
<a class="nav-link" href="#"><i class="fas fa-question-circle me-1"></i> Help</a> | |
</li> | |
</ul> | |
</div> | |
</div> | |
</nav> | |
<!-- Loading Overlay --> | |
<div class="loading-overlay" id="loadingOverlay"> | |
<div class="text-center mb-4"> | |
<i class="fas fa-spinner fa-spin fa-3x mb-3 pulse-icon"></i> | |
<h3 id="statusTitle" class="mb-3">Processing Your Video...</h3> | |
<p class="text-light opacity-75">This may take a few minutes depending on video length</p> | |
</div> | |
<div class="progress-container"> | |
<div class="progress"> | |
<div id="progressBar" class="progress-bar" | |
role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div> | |
</div> | |
<div class="d-flex justify-content-between mt-2"> | |
<small class="text-light opacity-75">Processing...</small> | |
<small id="progressText" class="text-light opacity-75">0%</small> | |
</div> | |
</div> | |
<!-- Success Alert (Hidden by default) --> | |
<div class="alert alert-success alert-dismissible fade show mt-4 w-75 mx-auto" role="alert" id="successAlert" style="display: none;"> | |
<div class="d-flex"> | |
<i class="fas fa-check-circle me-2 mt-1"></i> | |
<div> | |
<strong>Success!</strong> <span id="successMessage">The video has been processed successfully.</span> | |
</div> | |
</div> | |
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> | |
</div> | |
<!-- Error Alert (Hidden by default) --> | |
<div class="alert alert-danger alert-dismissible fade show mt-4 w-75 mx-auto" role="alert" id="errorAlert" style="display: none;"> | |
<div class="d-flex"> | |
<i class="fas fa-exclamation-circle me-2 mt-1"></i> | |
<div> | |
<strong>Error!</strong> <span id="errorMessage">An error occurred during processing.</span> | |
</div> | |
</div> | |
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> | |
</div> | |
<div class="log-container" id="logContainer"> | |
<!-- Log messages will be added here dynamically --> | |
</div> | |
</div> | |
<div class="container py-5"> | |
<!-- Banner --> | |
<div class="banner shadow-lg mb-5"> | |
<div class="container-fluid px-4"> | |
<div class="row align-items-center"> | |
<div class="col-md-8"> | |
<h2 class="display-5">Intelligent YouTube Transcript Analysis</h2> | |
<p>Transform video content into insightful summaries with AI-powered analysis in English and Hindi. Extract key points, topics, and quotes in seconds.</p> | |
</div> | |
<div class="col-md-4 text-md-end text-center mt-3 mt-md-0"> | |
<i class="fas fa-brain fa-5x opacity-50"></i> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Main Content --> | |
<div class="row"> | |
<div class="col-12 mb-4"> | |
<!-- Navigation Tabs --> | |
<ul class="nav nav-tabs" id="myTab" role="tablist"> | |
<li class="nav-item" role="presentation"> | |
<button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true"> | |
<i class="fas fa-play-circle"></i> Process Video | |
</button> | |
</li> | |
<li class="nav-item" role="presentation"> | |
<button class="nav-link" id="results-tab" data-bs-toggle="tab" data-bs-target="#results" type="button" role="tab" aria-controls="results" aria-selected="false"> | |
<i class="fas fa-list-ul"></i> Recent Results | |
</button> | |
</li> | |
<li class="nav-item" role="presentation"> | |
<button class="nav-link" id="preview-tab" data-bs-toggle="tab" data-bs-target="#preview" type="button" role="tab" aria-controls="preview" aria-selected="false"> | |
<i class="fas fa-file-alt"></i> Preview Content | |
</button> | |
</li> | |
</ul> | |
</div> | |
</div> | |
<div class="tab-content" id="myTabContent"> | |
<!-- Home Tab (Process Form) --> | |
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab"> | |
<div class="row"> | |
<div class="col-lg-8"> | |
<div class="card mb-4"> | |
<div class="card-header d-flex align-items-center"> | |
<i class="fas fa-link text-primary me-2"></i> | |
<span>Enter Video Details</span> | |
</div> | |
<div class="card-body"> | |
<form id="processingForm"> | |
<div class="mb-4"> | |
<label for="youtubeUrl" class="form-label">YouTube Video URL</label> | |
<div class="input-group mb-2"> | |
<span class="input-group-text"><i class="fab fa-youtube text-danger"></i></span> | |
<input type="url" class="form-control" id="youtubeUrl" name="youtube_url" | |
placeholder="https://www.youtube.com/watch?v=..." required> | |
</div> | |
<div class="form-text">Enter the full URL of any YouTube video you want to analyze</div> | |
</div> | |
<div class="mb-4"> | |
<label for="apiKey" class="form-label"></label> | |
<div class="input-group mb-2"> | |
<span class="input-group-text"><i class="fas fa-key"></i></span> | |
<input type="password" class="form-control" id="apiKey" name="api_key" | |
value="{{ api_key }}" required> | |
</div> | |
</div> | |
<div class="d-grid"> | |
<button type="submit" class="btn btn-primary btn-lg"> | |
<i class="fas fa-rocket me-2"></i> Process Video | |
</button> | |
</div> | |
</form> | |
</div> | |
</div> | |
</div> | |
<div class="col-lg-4"> | |
<div class="card help-card"> | |
<div class="card-header d-flex align-items-center"> | |
<i class="fas fa-info-circle text-primary me-2"></i> | |
<span>How It Works</span> | |
</div> | |
<div class="card-body"> | |
<div class="feature-item"> | |
<div class="features-icon"> | |
<i class="fas fa-download"></i> | |
</div> | |
<div class="feature-content"> | |
<h5>1. Fetch Transcript</h5> | |
<p class="text-muted">System automatically downloads video subtitles</p> | |
</div> | |
</div> | |
<div class="feature-item"> | |
<div class="features-icon"> | |
<i class="fas fa-robot"></i> | |
</div> | |
<div class="feature-content"> | |
<h5>2. AI Processing</h5> | |
<p class="text-muted"> AI analyzes and extracts key information</p> | |
</div> | |
</div> | |
<div class="feature-item"> | |
<div class="features-icon"> | |
<i class="fas fa-language"></i> | |
</div> | |
<div class="feature-content"> | |
<h5>3. Bilingual Output</h5> | |
<p class="text-muted">Get results in both English and Hindi</p> | |
</div> | |
</div> | |
<div class="feature-item"> | |
<div class="features-icon"> | |
<i class="fas fa-file-export"></i> | |
</div> | |
<div class="feature-content"> | |
<h5>4. Export & Share</h5> | |
<p class="text-muted">Download or preview your analysis results</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- What You Get Section --> | |
<div class="row mt-4"> | |
<div class="col-12"> | |
<div class="card"> | |
<div class="card-header d-flex align-items-center"> | |
<i class="fas fa-lightbulb text-primary me-2"></i> | |
<span>What You'll Get</span> | |
</div> | |
<div class="card-body"> | |
<div class="row g-4"> | |
<div class="col-md-3 col-sm-6"> | |
<div class="text-center"> | |
<div class="mb-3"> | |
<i class="fas fa-list-ul text-primary fa-2x"></i> | |
</div> | |
<h5>Key Points</h5> | |
<p class="text-muted small">Concise summary of main ideas</p> | |
</div> | |
</div> | |
<div class="col-md-3 col-sm-6"> | |
<div class="text-center"> | |
<div class="mb-3"> | |
<i class="fas fa-sitemap text-primary fa-2x"></i> | |
</div> | |
<h5>Topics Covered</h5> | |
<p class="text-muted small">Major themes and subjects</p> | |
</div> | |
</div> | |
<div class="col-md-3 col-sm-6"> | |
<div class="text-center"> | |
<div class="mb-3"> | |
<i class="fas fa-quote-right text-primary fa-2x"></i> | |
</div> | |
<h5>Notable Quotes</h5> | |
<p class="text-muted small">Important statements highlighted</p> | |
</div> | |
</div> | |
<div class="col-md-3 col-sm-6"> | |
<div class="text-center"> | |
<div class="mb-3"> | |
<i class="fas fa-align-left text-primary fa-2x"></i> | |
</div> | |
<h5>Full Transcript</h5> | |
<p class="text-muted small">Complete formatted content</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Results Tab --> | |
<div class="tab-pane fade" id="results" role="tabpanel" aria-labelledby="results-tab"> | |
<div class="card"> | |
<div class="card-header d-flex justify-content-between align-items-center"> | |
<div class="d-flex align-items-center"> | |
<i class="fas fa-history text-primary me-2"></i> | |
<span>Recent Analyses</span> | |
</div> | |
<button id="refreshResultsBtn" class="btn btn-sm btn-outline-primary"> | |
<i class="fas fa-sync-alt me-1"></i> Refresh | |
</button> | |
</div> | |
<div class="card-body p-0"> | |
<div class="table-responsive recent-items"> | |
<table class="table table-hover mb-0"> | |
<thead> | |
<tr> | |
<th class="px-3 py-3">Filename</th> | |
<th class="px-3 py-3">Language</th> | |
<th class="px-3 py-3">Created</th> | |
<th class="px-3 py-3 text-end">Actions</th> | |
</tr> | |
</thead> | |
<tbody id="resultsList"> | |
<!-- Results will be loaded here dynamically --> | |
<tr> | |
<td colspan="4" class="text-center p-4"> | |
<div class="spinner-border text-primary" role="status"> | |
<span class="visually-hidden">Loading...</span> | |
</div> | |
<p class="mt-2 text-muted">Loading results...</p> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Preview Tab --> | |
<div class="tab-pane fade" id="preview" role="tabpanel" aria-labelledby="preview-tab"> | |
<div class="card"> | |
<div class="card-header d-flex align-items-center mb-0"> | |
<i class="fas fa-file-alt text-primary me-2"></i> | |
<h5 id="previewTitle" class="m-0">No content selected</h5> | |
</div> | |
<div class="card-body"> | |
<div id="preview-container" class="markdown-body"> | |
<div class="text-center p-5 text-muted"> | |
<i class="far fa-file-alt fa-4x mb-3 opacity-25"></i> | |
<p>Select a result file from the "Recent Results" tab to preview content here</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Footer --> | |
<footer class="bg-dark text-light py-4 mt-5"> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-6"> | |
<h5 class="mb-3">TranscriptAI</h5> | |
</div> | |
<div class="col-md-6 text-md-end"> | |
<ul class="list-inline mb-0"> | |
<li class="list-inline-item"><a href="#" class="text-muted text-decoration-none">Terms</a></li> | |
<li class="list-inline-item"><a href="#" class="text-muted text-decoration-none">Privacy</a></li> | |
<li class="list-inline-item"><a href="#" class="text-muted text-decoration-none">Contact</a></li> | |
</ul> | |
<p class="mt-2 mb-0 text-muted small">© 2025 TranscriptAI. All rights reserved.</p> | |
</div> | |
</div> | |
</div> | |
</footer> | |
<!-- Bootstrap and jQuery JS | |
<!-- Bootstrap and jQuery JS --> | |
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
<script> | |
// Set up polling for status updates | |
let statusInterval; | |
let isProcessing = false; | |
// Initialize UI elements | |
$(document).ready(function() { | |
// Load results list on page load | |
loadResultsList(); | |
// Form submission handler | |
$('#processingForm').on('submit', function(e) { | |
e.preventDefault(); | |
startProcessing(); | |
}); | |
// Refresh results button | |
$('#refreshResultsBtn').on('click', function() { | |
loadResultsList(); | |
}); | |
}); | |
// Start processing a YouTube URL | |
function startProcessing() { | |
const youtubeUrl = $('#youtubeUrl').val().trim(); | |
const apiKey = $('#apiKey').val().trim(); | |
if (!youtubeUrl) { | |
alert('Please enter a valid YouTube URL'); | |
return; | |
} | |
// Show loading overlay | |
$('#loadingOverlay').fadeIn(); | |
$('#logContainer').empty(); | |
$('#progressBar').css('width', '0%'); | |
$('#progressText').text('0%'); | |
$('#statusTitle').text('Processing Your Video...'); | |
$('#successAlert').hide(); | |
$('#errorAlert').hide(); | |
// Submit request to server | |
$.ajax({ | |
url: '/process', | |
method: 'POST', | |
data: { | |
youtube_url: youtubeUrl, | |
api_key: apiKey | |
}, | |
success: function(response) { | |
if (response.success) { | |
// Start polling for status updates | |
isProcessing = true; | |
statusInterval = setInterval(checkStatus, 1000); | |
} else { | |
// Show error | |
$('#errorMessage').text(response.error); | |
$('#errorAlert').fadeIn(); | |
setTimeout(function() { | |
$('#loadingOverlay').fadeOut(); | |
}, 3000); | |
} | |
}, | |
error: function() { | |
$('#errorMessage').text('Server error. Please try again later.'); | |
$('#errorAlert').fadeIn(); | |
setTimeout(function() { | |
$('#loadingOverlay').fadeOut(); | |
}, 3000); | |
} | |
}); | |
} | |
// Check processing status | |
function checkStatus() { | |
$.ajax({ | |
url: '/status', | |
method: 'GET', | |
success: function(status) { | |
// Update progress bar | |
$('#progressBar').css('width', status.progress + '%'); | |
$('#progressText').text(status.progress + '%'); | |
$('#statusTitle').text(status.current_step); | |
// Update log | |
updateLog(status.log); | |
// Check if processing is complete | |
if (!status.is_processing && isProcessing) { | |
isProcessing = false; | |
clearInterval(statusInterval); | |
// Show success message | |
$('#successMessage').text('Processing complete! View your results in the "Recent Results" tab.'); | |
$('#successAlert').fadeIn(); | |
// Refresh results list | |
loadResultsList(); | |
// Switch to results tab after 3 seconds | |
setTimeout(function() { | |
$('#results-tab').tab('show'); | |
$('#loadingOverlay').fadeOut(); | |
}, 3000); | |
} | |
}, | |
error: function() { | |
clearInterval(statusInterval); | |
$('#errorMessage').text('Error checking status. Please try again.'); | |
$('#errorAlert').fadeIn(); | |
setTimeout(function() { | |
$('#loadingOverlay').fadeOut(); | |
}, 3000); | |
} | |
}); | |
} | |
// Update log display | |
function updateLog(logEntries) { | |
const logContainer = $('#logContainer'); | |
logContainer.empty(); | |
logEntries.forEach(function(entry) { | |
logContainer.append(`<div><span class="text-info">[${entry.time}]</span> ${entry.message}</div>`); | |
}); | |
// Auto-scroll to bottom | |
logContainer.scrollTop(logContainer[0].scrollHeight); | |
} | |
// Load results list | |
function loadResultsList() { | |
$.ajax({ | |
url: '/list_results', | |
method: 'GET', | |
success: function(files) { | |
const resultsList = $('#resultsList'); | |
resultsList.empty(); | |
if (files.length === 0) { | |
resultsList.append(` | |
<tr> | |
<td colspan="4" class="text-center p-4"> | |
<i class="far fa-file-alt fa-3x mb-3 text-muted opacity-25"></i> | |
<p class="text-muted">No results found. Process a video to get started.</p> | |
</td> | |
</tr> | |
`); | |
return; | |
} | |
files.forEach(function(file) { | |
const date = new Date(file.created * 1000); | |
const formattedDate = date.toLocaleString(); | |
const isHindi = file.is_hindi; | |
resultsList.append(` | |
<tr> | |
<td class="px-3 py-3"> | |
<div class="d-flex align-items-center"> | |
<i class="far fa-file-alt text-${isHindi ? 'danger' : 'primary'} me-2"></i> | |
<span>${file.filename}</span> | |
</div> | |
</td> | |
<td class="px-3 py-3"> | |
<span class="badge ${isHindi ? 'badge-hindi' : 'badge-english'}"> | |
${isHindi ? 'Hindi' : 'English'} | |
</span> | |
</td> | |
<td class="px-3 py-3">${formattedDate}</td> | |
<td class="px-3 py-3 text-end"> | |
<button class="btn btn-sm btn-outline-primary btn-action view-result" | |
data-filename="${file.filename}"> | |
<i class="fas fa-eye"></i> View | |
</button> | |
<a href="/results/${file.filename}" class="btn btn-sm btn-outline-success btn-action" download> | |
<i class="fas fa-download"></i> Download | |
</a> | |
</td> | |
</tr> | |
`); | |
}); | |
// Attach event handlers to view buttons | |
$('.view-result').on('click', function() { | |
const filename = $(this).data('filename'); | |
viewResult(filename); | |
}); | |
}, | |
error: function() { | |
const resultsList = $('#resultsList'); | |
resultsList.empty(); | |
resultsList.append(` | |
<tr> | |
<td colspan="4" class="text-center p-4"> | |
<i class="fas fa-exclamation-circle fa-3x mb-3 text-danger opacity-25"></i> | |
<p class="text-danger">Error loading results. Please try again.</p> | |
</td> | |
</tr> | |
`); | |
} | |
}); | |
} | |
// View a result file | |
function viewResult(filename) { | |
// Switch to preview tab | |
$('#preview-tab').tab('show'); | |
// Set preview title | |
$('#previewTitle').text(filename); | |
// Show loading state | |
$('#preview-container').html(` | |
<div class="text-center p-5"> | |
<div class="spinner-border text-primary" role="status"> | |
<span class="visually-hidden">Loading...</span> | |
</div> | |
<p class="mt-3 text-muted">Loading content...</p> | |
</div> | |
`); | |
// Fetch and display the content | |
$.ajax({ | |
url: `/results/${filename}`, | |
method: 'GET', | |
success: function(content) { | |
// Convert markdown to HTML | |
const htmlContent = marked.parse(content); | |
$('#preview-container').html(htmlContent); | |
}, | |
error: function() { | |
$('#preview-container').html(` | |
<div class="text-center p-5 text-danger"> | |
<i class="fas fa-exclamation-circle fa-4x mb-3 opacity-25"></i> | |
<p>Error loading content. Please try again.</p> | |
</div> | |
`); | |
} | |
}); | |
} | |
</script> | |
</body> | |
</html> |