Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -129,7 +129,7 @@ def extract_audio(video_path, output_dir):
|
|
| 129 |
return audio_path
|
| 130 |
|
| 131 |
# ----------------------------------------------------------
|
| 132 |
-
# Generate the annotated HTML transcript with category selection
|
| 133 |
# ----------------------------------------------------------
|
| 134 |
def generate_html(entries, video_id, video_path, screenshot_dir, plot_dir, output_html_path):
|
| 135 |
dispositif_options = [
|
|
@@ -165,6 +165,7 @@ def generate_html(entries, video_id, video_path, screenshot_dir, plot_dir, outpu
|
|
| 165 |
<head>
|
| 166 |
<meta charset="UTF-8">
|
| 167 |
<title>{video_id}</title>
|
|
|
|
| 168 |
<style>
|
| 169 |
body {{ font-family: Arial; font-size: 18px; margin: 20px; }}
|
| 170 |
.media img {{ width: 480px; height: auto; border: 1px solid #ccc; border-radius: 6px; box-shadow: 2px 2px 6px rgba(0,0,0,0.1); }}
|
|
@@ -172,11 +173,14 @@ body {{ font-family: Arial; font-size: 18px; margin: 20px; }}
|
|
| 172 |
.text {{ flex: 2; }}
|
| 173 |
.media {{ flex: 3; display: flex; flex-direction: column; gap: 10px; }}
|
| 174 |
select, textarea {{ width: 100%; margin-top: 5px; }}
|
|
|
|
| 175 |
</style>
|
| 176 |
</head>
|
| 177 |
<body>
|
| 178 |
<h1>Annotated Transcript for {video_id}</h1>
|
| 179 |
<p>Uploaded video file: {os.path.basename(video_path)}</p>
|
|
|
|
|
|
|
| 180 |
"""
|
| 181 |
|
| 182 |
for idx, (time_range, text) in enumerate(entries):
|
|
@@ -215,6 +219,7 @@ select, textarea {{ width: 100%; margin-top: 5px; }}
|
|
| 215 |
</div>
|
| 216 |
"""
|
| 217 |
|
|
|
|
| 218 |
html += """
|
| 219 |
<script>
|
| 220 |
function applyNext(selectElem, cls) {
|
|
@@ -229,6 +234,32 @@ function applyNext(selectElem, cls) {
|
|
| 229 |
if(seg.contains(selectElem)) found = true;
|
| 230 |
});
|
| 231 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
</script>
|
| 233 |
"""
|
| 234 |
|
|
@@ -306,7 +337,7 @@ Upload a video and get:
|
|
| 306 |
2. VTT subtitles
|
| 307 |
3. Screenshots (ZIP)
|
| 308 |
4. Voice intensity plots
|
| 309 |
-
5. Interactive HTML with editable text, screenshots, voice plots,
|
| 310 |
"""
|
| 311 |
|
| 312 |
demo = gr.Interface(
|
|
|
|
| 129 |
return audio_path
|
| 130 |
|
| 131 |
# ----------------------------------------------------------
|
| 132 |
+
# Generate the annotated HTML transcript with category selection & XLSX export
|
| 133 |
# ----------------------------------------------------------
|
| 134 |
def generate_html(entries, video_id, video_path, screenshot_dir, plot_dir, output_html_path):
|
| 135 |
dispositif_options = [
|
|
|
|
| 165 |
<head>
|
| 166 |
<meta charset="UTF-8">
|
| 167 |
<title>{video_id}</title>
|
| 168 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
|
| 169 |
<style>
|
| 170 |
body {{ font-family: Arial; font-size: 18px; margin: 20px; }}
|
| 171 |
.media img {{ width: 480px; height: auto; border: 1px solid #ccc; border-radius: 6px; box-shadow: 2px 2px 6px rgba(0,0,0,0.1); }}
|
|
|
|
| 173 |
.text {{ flex: 2; }}
|
| 174 |
.media {{ flex: 3; display: flex; flex-direction: column; gap: 10px; }}
|
| 175 |
select, textarea {{ width: 100%; margin-top: 5px; }}
|
| 176 |
+
button {{ padding: 10px 15px; font-size: 16px; margin-bottom: 20px; }}
|
| 177 |
</style>
|
| 178 |
</head>
|
| 179 |
<body>
|
| 180 |
<h1>Annotated Transcript for {video_id}</h1>
|
| 181 |
<p>Uploaded video file: {os.path.basename(video_path)}</p>
|
| 182 |
+
|
| 183 |
+
<button onclick="exportToExcel()">Export to XLSX</button>
|
| 184 |
"""
|
| 185 |
|
| 186 |
for idx, (time_range, text) in enumerate(entries):
|
|
|
|
| 219 |
</div>
|
| 220 |
"""
|
| 221 |
|
| 222 |
+
# JavaScript functions for apply-next and export
|
| 223 |
html += """
|
| 224 |
<script>
|
| 225 |
function applyNext(selectElem, cls) {
|
|
|
|
| 234 |
if(seg.contains(selectElem)) found = true;
|
| 235 |
});
|
| 236 |
}
|
| 237 |
+
|
| 238 |
+
function exportToExcel() {
|
| 239 |
+
let segments = document.querySelectorAll('.segment');
|
| 240 |
+
let data = [];
|
| 241 |
+
segments.forEach((seg, idx) => {
|
| 242 |
+
let time = seg.querySelector('h3').innerText;
|
| 243 |
+
let text = seg.querySelector('p').innerText;
|
| 244 |
+
let dispositif = seg.querySelector('.dispositif').value;
|
| 245 |
+
let dispositif_comment = seg.querySelector('textarea:nth-of-type(1)').value;
|
| 246 |
+
let thematic = seg.querySelector('.thematic').value;
|
| 247 |
+
let thematic_comment = seg.querySelector('textarea:nth-of-type(2)').value;
|
| 248 |
+
data.push({
|
| 249 |
+
"Segment #": idx + 1,
|
| 250 |
+
"Time": time,
|
| 251 |
+
"Transcript": text,
|
| 252 |
+
"Dispositif médiatique": dispositif,
|
| 253 |
+
"Commentaire dispositif": dispositif_comment,
|
| 254 |
+
"Catégorie thématique": thematic,
|
| 255 |
+
"Commentaire thématique": thematic_comment
|
| 256 |
+
});
|
| 257 |
+
});
|
| 258 |
+
let ws = XLSX.utils.json_to_sheet(data);
|
| 259 |
+
let wb = XLSX.utils.book_new();
|
| 260 |
+
XLSX.utils.book_append_sheet(wb, ws, "Transcript");
|
| 261 |
+
XLSX.writeFile(wb, "annotated_transcript.xlsx");
|
| 262 |
+
}
|
| 263 |
</script>
|
| 264 |
"""
|
| 265 |
|
|
|
|
| 337 |
2. VTT subtitles
|
| 338 |
3. Screenshots (ZIP)
|
| 339 |
4. Voice intensity plots
|
| 340 |
+
5. Interactive HTML with editable text, screenshots, voice plots, category selection, and XLSX export.
|
| 341 |
"""
|
| 342 |
|
| 343 |
demo = gr.Interface(
|