|
|
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Video Accent Analyzer</title> |
|
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script> |
|
<style> |
|
body { |
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
max-width: 1000px; |
|
margin: 0 auto; |
|
padding: 20px; |
|
background-color: #f5f5f5; |
|
} |
|
.container { |
|
background: white; |
|
padding: 20px; |
|
border-radius: 10px; |
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1); |
|
} |
|
.input-group { |
|
margin-bottom: 20px; |
|
} |
|
input, button { |
|
padding: 10px; |
|
margin: 5px 0; |
|
border-radius: 5px; |
|
border: 1px solid #ddd; |
|
} |
|
input[type="text"] { |
|
width: 100%; |
|
box-sizing: border-box; |
|
} |
|
button { |
|
background: linear-gradient(45deg, #4CAF50, #2196F3); |
|
color: white; |
|
border: none; |
|
cursor: pointer; |
|
transition: transform 0.2s; |
|
} |
|
button:hover { |
|
transform: scale(1.02); |
|
} |
|
#results { |
|
margin-top: 20px; |
|
padding: 20px; |
|
border-radius: 5px; |
|
background-color: #f8f9fa; |
|
} |
|
.error { |
|
color: red; |
|
padding: 10px; |
|
background-color: #fee; |
|
border-radius: 5px; |
|
} |
|
#plot { |
|
margin-top: 20px; |
|
} |
|
.metric { |
|
display: inline-block; |
|
padding: 10px; |
|
margin: 5px; |
|
background: #fff; |
|
border-radius: 5px; |
|
box-shadow: 0 1px 3px rgba(0,0,0,0.1); |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<h1>🎧 Video Accent Analyzer</h1> |
|
|
|
<div class="input-group"> |
|
<input type="text" id="videoUrl" placeholder="Enter YouTube, Loom, or direct video URL"> |
|
<input type="number" id="duration" value="30" min="10" max="120" step="10"> |
|
<button onclick="analyzeVideo()">Analyze Video</button> |
|
</div> |
|
|
|
<div id="loading" style="display: none;"> |
|
Analyzing video... Please wait... |
|
</div> |
|
|
|
<div id="results" style="display: none;"></div> |
|
<div id="plot"></div> |
|
</div> |
|
|
|
<script> |
|
async function analyzeVideo() { |
|
const url = document.getElementById('videoUrl').value; |
|
const duration = document.getElementById('duration').value; |
|
const loading = document.getElementById('loading'); |
|
const results = document.getElementById('results'); |
|
const plot = document.getElementById('plot'); |
|
|
|
if (!url) { |
|
alert('Please enter a video URL'); |
|
return; |
|
} |
|
|
|
loading.style.display = 'block'; |
|
results.style.display = 'none'; |
|
plot.innerHTML = ''; |
|
|
|
try { |
|
const response = await fetch('/api/analyze', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
}, |
|
body: JSON.stringify({ url, duration }), |
|
}); |
|
|
|
const data = await response.json(); |
|
|
|
if (data.error) { |
|
results.innerHTML = `<div class="error">Error: ${data.error}</div>`; |
|
results.style.display = 'block'; |
|
return; |
|
} |
|
|
|
|
|
results.innerHTML = ` |
|
<h2>Analysis Results</h2> |
|
<div class="metric"> |
|
<strong>Predicted Accent:</strong><br> |
|
${data.predicted_accent} |
|
</div> |
|
<div class="metric"> |
|
<strong>Confidence:</strong><br> |
|
${data.accent_confidence.toFixed(1)}% |
|
</div> |
|
<div class="metric"> |
|
<strong>English Confidence:</strong><br> |
|
${data.english_confidence.toFixed(1)}% |
|
</div> |
|
<div class="metric"> |
|
<strong>Audio Duration:</strong><br> |
|
${data.audio_duration.toFixed(1)}s |
|
</div> |
|
`; |
|
|
|
|
|
Plotly.newPlot('plot', data.plot.data, data.plot.layout); |
|
results.style.display = 'block'; |
|
|
|
} catch (error) { |
|
results.innerHTML = `<div class="error">Error: ${error.message}</div>`; |
|
results.style.display = 'block'; |
|
} finally { |
|
loading.style.display = 'none'; |
|
} |
|
} |
|
</script> |
|
</body> |
|
</html> |