Manjunath Kudlur commited on
Commit
252a98f
·
1 Parent(s): 82b533a

Mobile friendly

Browse files
Files changed (2) hide show
  1. index.html +214 -0
  2. streaming_asr.js +33 -0
index.html CHANGED
@@ -376,6 +376,212 @@
376
  .error-message.visible {
377
  display: block;
378
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  </style>
380
  </head>
381
  <body>
@@ -394,6 +600,14 @@
394
  </div>
395
 
396
  <div class="container">
 
 
 
 
 
 
 
 
397
  <h1>Streaming ASR Demo</h1>
398
 
399
  <div class="error-message" id="errorMessage"></div>
 
376
  .error-message.visible {
377
  display: block;
378
  }
379
+
380
+ /* Mobile-first live caption - shown at top on mobile */
381
+ .live-caption-mobile {
382
+ display: none;
383
+ }
384
+
385
+ /* Mobile styles */
386
+ @media (max-width: 768px) {
387
+ body {
388
+ padding: 10px;
389
+ }
390
+
391
+ h1 {
392
+ font-size: 1.4rem;
393
+ margin-bottom: 15px;
394
+ }
395
+
396
+ /* Show mobile live caption at top */
397
+ .live-caption-mobile {
398
+ display: block;
399
+ position: sticky;
400
+ top: 0;
401
+ z-index: 100;
402
+ margin: -10px -10px 15px -10px;
403
+ padding: 20px 15px;
404
+ background: rgba(0, 0, 0, 0.9);
405
+ border-radius: 0 0 12px 12px;
406
+ min-height: 80px;
407
+ text-align: center;
408
+ backdrop-filter: blur(10px);
409
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
410
+ }
411
+
412
+ .live-caption-mobile.active {
413
+ background: rgba(20, 0, 0, 0.95);
414
+ box-shadow: 0 4px 20px rgba(255, 68, 68, 0.2);
415
+ }
416
+
417
+ .live-caption-mobile .live-caption-label {
418
+ font-size: 10px;
419
+ color: rgba(255, 255, 255, 0.5);
420
+ text-transform: uppercase;
421
+ letter-spacing: 2px;
422
+ margin-bottom: 8px;
423
+ }
424
+
425
+ .live-caption-mobile.active .live-caption-label {
426
+ color: #ff6b6b;
427
+ }
428
+
429
+ .live-caption-mobile .live-caption-text {
430
+ font-size: 22px;
431
+ font-weight: 400;
432
+ line-height: 1.4;
433
+ color: #ffffff;
434
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
435
+ }
436
+
437
+ .live-caption-mobile .live-caption-text.placeholder {
438
+ color: rgba(255, 255, 255, 0.35);
439
+ font-style: italic;
440
+ font-size: 16px;
441
+ font-weight: 300;
442
+ }
443
+
444
+ /* Hide desktop live caption on mobile */
445
+ .transcripts-section .live-caption {
446
+ display: none;
447
+ }
448
+
449
+ /* Compact status bar */
450
+ .status-bar {
451
+ flex-direction: column;
452
+ gap: 12px;
453
+ padding: 12px 15px;
454
+ }
455
+
456
+ .controls {
457
+ width: 100%;
458
+ justify-content: center;
459
+ }
460
+
461
+ button {
462
+ padding: 12px 24px;
463
+ font-size: 16px;
464
+ min-height: 44px;
465
+ }
466
+
467
+ /* Collapsible config section */
468
+ .config-section {
469
+ padding: 15px;
470
+ }
471
+
472
+ .config-section h3 {
473
+ cursor: pointer;
474
+ display: flex;
475
+ justify-content: space-between;
476
+ align-items: center;
477
+ }
478
+
479
+ .config-section h3::after {
480
+ content: '▼';
481
+ font-size: 12px;
482
+ transition: transform 0.2s;
483
+ }
484
+
485
+ .config-section.collapsed h3::after {
486
+ transform: rotate(-90deg);
487
+ }
488
+
489
+ .config-section.collapsed .config-grid {
490
+ display: none;
491
+ }
492
+
493
+ .config-grid {
494
+ grid-template-columns: 1fr;
495
+ gap: 12px;
496
+ }
497
+
498
+ .config-item select,
499
+ .config-item input {
500
+ padding: 12px;
501
+ font-size: 16px;
502
+ min-height: 44px;
503
+ }
504
+
505
+ /* Collapsible VAD section */
506
+ .vad-section {
507
+ padding: 15px;
508
+ }
509
+
510
+ .vad-section h3 {
511
+ cursor: pointer;
512
+ display: flex;
513
+ justify-content: space-between;
514
+ align-items: center;
515
+ }
516
+
517
+ .vad-section h3::after {
518
+ content: '▼';
519
+ font-size: 12px;
520
+ transition: transform 0.2s;
521
+ }
522
+
523
+ .vad-section.collapsed h3::after {
524
+ transform: rotate(-90deg);
525
+ }
526
+
527
+ .vad-section.collapsed .vad-graph,
528
+ .vad-section.collapsed .vad-bar,
529
+ .vad-section.collapsed .pipeline-status {
530
+ display: none;
531
+ }
532
+
533
+ .vad-graph {
534
+ height: 80px;
535
+ }
536
+
537
+ .pipeline-status {
538
+ flex-wrap: wrap;
539
+ gap: 10px;
540
+ }
541
+
542
+ /* Transcripts section */
543
+ .transcripts-section {
544
+ padding: 15px;
545
+ min-height: auto;
546
+ }
547
+
548
+ .transcripts-list {
549
+ max-height: 150px;
550
+ }
551
+
552
+ .transcript-item {
553
+ padding: 8px 12px;
554
+ font-size: 14px;
555
+ }
556
+
557
+ /* Loading overlay mobile */
558
+ .loading-progress {
559
+ width: 250px;
560
+ }
561
+
562
+ .loading-text {
563
+ font-size: 16px;
564
+ }
565
+ }
566
+
567
+ /* Extra small screens */
568
+ @media (max-width: 400px) {
569
+ .live-caption-mobile .live-caption-text {
570
+ font-size: 18px;
571
+ }
572
+
573
+ h1 {
574
+ font-size: 1.2rem;
575
+ }
576
+
577
+ .controls {
578
+ flex-direction: column;
579
+ }
580
+
581
+ button {
582
+ width: 100%;
583
+ }
584
+ }
585
  </style>
586
  </head>
587
  <body>
 
600
  </div>
601
 
602
  <div class="container">
603
+ <!-- Mobile live caption at top (hidden on desktop) -->
604
+ <div class="live-caption-mobile" id="liveCaptionMobile">
605
+ <div class="live-caption-label">Live Caption</div>
606
+ <div class="live-caption-text placeholder" id="liveCaptionTextMobile">
607
+ Waiting for speech...
608
+ </div>
609
+ </div>
610
+
611
  <h1>Streaming ASR Demo</h1>
612
 
613
  <div class="error-message" id="errorMessage"></div>
streaming_asr.js CHANGED
@@ -675,6 +675,8 @@ class ASRDemoUI {
675
  this.transcriptsList = document.getElementById('transcriptsList');
676
  this.liveCaption = document.getElementById('liveCaption');
677
  this.liveCaptionText = document.getElementById('liveCaptionText');
 
 
678
  this.modelSelect = document.getElementById('modelSelect');
679
  this.onnxUrl = document.getElementById('onnxUrl');
680
  this.onsetThreshold = document.getElementById('onsetThreshold');
@@ -694,6 +696,27 @@ class ASRDemoUI {
694
  bindEvents() {
695
  this.startBtn.addEventListener('click', () => this.handleStart());
696
  this.stopBtn.addEventListener('click', () => this.handleStop());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
697
  }
698
 
699
  async handleStart() {
@@ -809,13 +832,23 @@ class ASRDemoUI {
809
 
810
  updateLiveCaption(text) {
811
  if (text) {
 
812
  this.liveCaptionText.textContent = text;
813
  this.liveCaptionText.classList.remove('placeholder');
814
  this.liveCaption.classList.add('active');
 
 
 
 
815
  } else {
 
816
  this.liveCaptionText.textContent = 'Waiting for speech...';
817
  this.liveCaptionText.classList.add('placeholder');
818
  this.liveCaption.classList.remove('active');
 
 
 
 
819
  }
820
  }
821
 
 
675
  this.transcriptsList = document.getElementById('transcriptsList');
676
  this.liveCaption = document.getElementById('liveCaption');
677
  this.liveCaptionText = document.getElementById('liveCaptionText');
678
+ this.liveCaptionMobile = document.getElementById('liveCaptionMobile');
679
+ this.liveCaptionTextMobile = document.getElementById('liveCaptionTextMobile');
680
  this.modelSelect = document.getElementById('modelSelect');
681
  this.onnxUrl = document.getElementById('onnxUrl');
682
  this.onsetThreshold = document.getElementById('onsetThreshold');
 
696
  bindEvents() {
697
  this.startBtn.addEventListener('click', () => this.handleStart());
698
  this.stopBtn.addEventListener('click', () => this.handleStop());
699
+
700
+ // Mobile: collapsible sections
701
+ const configSection = document.querySelector('.config-section');
702
+ const vadSection = document.querySelector('.vad-section');
703
+
704
+ configSection?.querySelector('h3')?.addEventListener('click', () => {
705
+ configSection.classList.toggle('collapsed');
706
+ });
707
+
708
+ vadSection?.querySelector('h3')?.addEventListener('click', () => {
709
+ vadSection.classList.toggle('collapsed');
710
+ // Re-init canvas on expand in case it needs redrawing
711
+ if (!vadSection.classList.contains('collapsed')) {
712
+ this.initCanvas();
713
+ }
714
+ });
715
+
716
+ // Start with config collapsed on mobile
717
+ if (window.innerWidth <= 768) {
718
+ configSection?.classList.add('collapsed');
719
+ }
720
  }
721
 
722
  async handleStart() {
 
832
 
833
  updateLiveCaption(text) {
834
  if (text) {
835
+ // Desktop
836
  this.liveCaptionText.textContent = text;
837
  this.liveCaptionText.classList.remove('placeholder');
838
  this.liveCaption.classList.add('active');
839
+ // Mobile
840
+ this.liveCaptionTextMobile.textContent = text;
841
+ this.liveCaptionTextMobile.classList.remove('placeholder');
842
+ this.liveCaptionMobile.classList.add('active');
843
  } else {
844
+ // Desktop
845
  this.liveCaptionText.textContent = 'Waiting for speech...';
846
  this.liveCaptionText.classList.add('placeholder');
847
  this.liveCaption.classList.remove('active');
848
+ // Mobile
849
+ this.liveCaptionTextMobile.textContent = 'Waiting for speech...';
850
+ this.liveCaptionTextMobile.classList.add('placeholder');
851
+ this.liveCaptionMobile.classList.remove('active');
852
  }
853
  }
854