QuadraV commited on
Commit
47a61a9
·
verified ·
1 Parent(s): a3299b5

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +272 -254
index.html CHANGED
@@ -364,6 +364,7 @@
364
  justify-content: space-around;
365
  align-items: center;
366
  }
 
367
 
368
  </style>
369
  </head>
@@ -433,6 +434,7 @@
433
  <button id="exportSrtBtn" class="export-button" onclick="exportAsrData('srt')">导出 SRT</button>
434
  <!-- 修改合成按钮颜色 -->
435
  <button id="generateSubtitleBtn" class="subtitle-button" onclick="generateSubtitle()">合成字幕</button>
 
436
  </div>
437
  </div>
438
  </div>
@@ -446,157 +448,192 @@
446
  </footer>
447
 
448
  <script>
449
- let currentTaskId = null; // 当前的任务ID
450
  let asrData = []; // 存储识别结果数据
451
  let serverUrl = null; // 服务器地址
 
452
 
453
  // 监听文件输入更改,预览视频
454
  document.getElementById('videoInput').addEventListener('change', function (event) {
455
  const file = event.target.files[0];
456
- console.log('Selected file:', file);
457
  document.getElementById('uploadBtn').disabled = file.size > 300 * 1024 * 1024;
458
 
459
  const videoPlayer = document.getElementById('videoPlayer');
460
- const videoURL = URL.createObjectURL(file);
461
- console.log('Video URL:', videoURL);
462
- videoPlayer.src = videoURL;
463
  });
464
-
465
  // 上传文件并提交任务
466
  function uploadFile() {
467
  const fileInput = document.getElementById('videoInput');
468
  const file = fileInput.files[0];
469
-
470
  if (!file) {
471
  alert('请先选择一个文件');
472
  return;
473
  }
474
-
475
- // 获取文件的 MIME 类型
476
- const fileType = file.type;
477
- console.log('File type:', fileType);
478
-
479
- // 检查是否为视频文件
480
- const validVideoTypes = ['video/mp4', 'video/x-m4v', 'video/*', 'audio/mp4'];
481
- const isVideo = validVideoTypes.includes(fileType);
482
- console.log('Is valid video:', isVideo);
483
-
484
- // 保存文件类型到全局变量
485
- window.currentFileType = fileType;
486
-
487
- // 获取选择的任务类型
488
  const speakerRecognition = document.getElementById('speakerRecognition').checked;
489
  const englishTranslation = document.getElementById('englishTranslation').checked;
490
- console.log('Speaker Recognition:', speakerRecognition, 'English Translation:', englishTranslation);
491
-
492
- // 获取用户选择的识别模型
493
  const selectedPipeline = document.querySelector('input[name="pipeline"]:checked').value;
494
- console.log('Selected pipeline:', selectedPipeline);
495
-
 
 
496
  document.getElementById('uploadBtn').disabled = true;
497
- document.getElementById('uploadBtn').innerText = '转写中...';
498
-
499
  resetProgress();
500
-
501
- // 从输入框获取服务器地址
502
  serverUrl = document.getElementById('serverUrlInput').value.trim();
503
- console.log('Server URL:', serverUrl);
504
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  const xhr = new XMLHttpRequest();
506
  xhr.open('POST', `${serverUrl}/submit`, true);
507
- xhr.upload.onprogress = updateUploadProgress;
508
  xhr.onload = function () {
509
- console.log('Upload response status:', xhr.status);
510
  if (xhr.status === 200) {
511
  const response = JSON.parse(xhr.responseText);
512
- console.log('Upload response:', response);
513
  if (response.code === 0) {
514
- currentTaskId = response.content; // 获取任务ID
515
- console.log('Task ID:', currentTaskId);
516
- monitorTaskProgress(currentTaskId);
517
  } else {
518
- alert('上传失败,请重试');
519
  resetUploadButton();
520
  }
521
  } else {
522
- alert('上传失败,请重试');
523
  resetUploadButton();
524
  }
525
  };
526
  xhr.onerror = handleUploadError;
527
-
528
- const formData = new FormData();
529
- formData.append('file', file);
530
- formData.append('speakerRecognition', speakerRecognition); // 传递说话人识别参数
531
- formData.append('englishTranslation', englishTranslation); // 传递英文翻译参数
532
- formData.append('pipeline', selectedPipeline); // 传递选择的识别模型
533
- console.log('Form Data:', formData);
534
  xhr.send(formData);
535
  }
536
-
537
- // 重置进度条和界面
538
- function resetProgress() {
539
- console.log('Resetting progress bars and UI elements');
540
- document.getElementById('uploadProgress').firstElementChild.style.width = '0%';
541
- document.getElementById('uploadProgress').firstElementChild.innerText = '';
542
- document.getElementById('recognitionProgress').firstElementChild.style.width = '0%';
543
- document.getElementById('recognitionProgress').firstElementChild.innerText = '';
544
- document.getElementById('subtitleProgress').firstElementChild.style.width = '0%';
545
- document.getElementById('subtitleProgress').firstElementChild.innerText = '';
546
- document.getElementById('asrList').innerHTML = "";
547
- document.getElementById('logContent').innerText = "";
548
- }
549
 
550
- // 更新上传进度
551
- function updateUploadProgress(event) {
552
- if (event.lengthComputable) {
553
- const percentComplete = (event.loaded / event.total) * 100;
554
- console.log('Upload progress:', percentComplete);
555
- document.getElementById('uploadProgress').firstElementChild.style.width = `${percentComplete}%`;
556
- document.getElementById('uploadProgress').firstElementChild.innerText = `${percentComplete.toFixed(2)}%`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
557
  }
 
 
558
  }
559
 
560
- // 上传失败的处理
561
- function handleUploadError() {
562
- console.log('Upload error occurred');
563
- alert('上传失败,请重试');
564
- resetUploadButton();
 
565
  }
566
 
567
- // 重置上传按钮状态
568
- function resetUploadButton() {
569
- console.log('Resetting upload button state');
570
- document.getElementById('uploadBtn').disabled = false;
571
- document.getElementById('uploadBtn').innerText = '上传并识别';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
572
  }
573
 
574
  // 监控任务进度
575
  function monitorTaskProgress(taskId) {
576
- console.log('Monitoring task progress for Task ID:', taskId);
577
- let failedRequests = 0; // 计数连续失败的请求
578
- const maxFailedRequests = 10; // 连续失败的最大请求数
579
-
580
  const intervalId = setInterval(function () {
581
  const xhr = new XMLHttpRequest();
582
- xhr.open('GET', `${serverUrl}/task_prgs/${taskId}`, true);
583
  xhr.onload = function () {
584
- console.log('Progress response status:', xhr.status);
585
  if (xhr.status === 200) {
586
  const response = JSON.parse(xhr.responseText);
587
- console.log('Progress response:', response);
588
  const status = response.content.status;
589
  const progress = response.content.prgs;
590
  failedRequests = 0;
591
-
592
  if (progress) {
593
- updateRecognitionProgress(progress.cur / progress.total * 100, progress.msg);
594
  }
595
-
596
  if (status === "SUCCESS") {
597
  clearInterval(intervalId);
598
  asrData = response.content.result;
599
- console.log('Recognition successful, ASR data:', asrData);
600
  displayResults(asrData);
601
  resetUploadButton();
602
  } else if (status === "FAIL") {
@@ -605,31 +642,28 @@
605
  resetUploadButton();
606
  }
607
  } else {
608
- failedRequests += 1; // 增加失败计数
609
- document.getElementById('logContent').innerText = `请求失败,当前重连次数: ${failedRequests}`;
610
- if (failedRequests >= maxFailedRequests) {
611
- clearInterval(intervalId);
612
- alert('连续请求失败,任务未完成');
613
- resetUploadButton();
614
- }
615
- }
616
- };
617
- xhr.onerror = function () {
618
- failedRequests += 1; // 增加失败计数
619
- document.getElementById('logContent').innerText = `请求失败,当前重连次数: ${failedRequests}`;
620
- if (failedRequests >= maxFailedRequests) {
621
- clearInterval(intervalId);
622
- alert('连续请求失败,任务未完成');
623
- resetUploadButton();
624
  }
625
  };
 
626
  xhr.send();
627
  }, 2000);
628
  }
629
-
 
 
 
 
 
 
 
 
 
 
 
630
  // 更新识别进度
631
  function updateRecognitionProgress(progress, msg) {
632
- console.log('Recognition progress:', progress, 'Message:', msg);
633
  document.getElementById('recognitionProgress').firstElementChild.style.width = `${progress}%`;
634
  document.getElementById('recognitionProgress').firstElementChild.innerText = `${progress.toFixed(2)}%`;
635
  document.getElementById('logContent').innerText = `进度: ${progress.toFixed(2)}%, 状态: ${msg}`;
@@ -637,7 +671,7 @@
637
 
638
  // 显示识别结果
639
  function displayResults(results) {
640
- console.log('Displaying ASR results:', results);
641
  const asrList = document.getElementById('asrList');
642
  asrList.innerHTML = "";
643
  results.forEach((entry) => {
@@ -659,210 +693,194 @@
659
  </label>
660
  `;
661
 
662
- const startInput = div.querySelector('.start-time');
663
- const endInput = div.querySelector('.end-time');
664
- const roleInput = div.querySelector('input.role-field');
665
- const textInput = div.querySelector('input.text-field');
666
- const transInput = div.querySelector('input.trans-field');
667
- const dropCheckbox = div.querySelector('input[type="checkbox"]');
668
- const playButton = div.querySelector('.play-button');
669
-
670
- startInput.addEventListener('input', () => {
671
- entry.start = parseFloat(startInput.value);
672
- });
673
-
674
- endInput.addEventListener('input', () => {
675
- entry.end = parseFloat(endInput.value);
676
- });
677
-
678
- roleInput.addEventListener('input', () => {
679
- entry.role = roleInput.value;
680
- });
681
-
682
- textInput.addEventListener('input', () => {
683
- entry.text = textInput.value;
684
- });
685
-
686
- transInput.addEventListener('input', () => {
687
- entry.trans = transInput.value;
688
- });
689
-
690
- dropCheckbox.addEventListener('change', () => {
691
- entry.drop = dropCheckbox.checked;
692
- });
693
-
694
- playButton.addEventListener('click', () => {
695
- const video = document.getElementById('videoPlayer');
696
- video.currentTime = entry.start;
697
- video.play();
698
- const interval = setInterval(() => {
699
- if (video.currentTime >= entry.end) {
700
- video.pause();
701
- clearInterval(interval);
702
- }
703
- }, 100);
704
- });
705
-
706
  asrList.appendChild(div);
707
  });
708
  }
709
 
710
- // 导出识别结果为 JSON 或 SRT 格式
711
- function exportAsrData(format) {
712
- if (asrData.length === 0) {
713
- alert('没有数据可以导出');
714
- return;
715
- }
716
-
717
- // 过滤掉被标记为丢弃的条目
718
- const filteredData = asrData.filter(entry => !entry.drop);
719
-
720
- let content = '';
721
- if (format === 'json') {
722
- content = JSON.stringify(filteredData, null, 2);
723
- } else if (format === 'srt') {
724
- filteredData.forEach((entry, index) => {
725
- content += `${index + 1}\n`;
726
- const start = formatTime(entry.start);
727
- const end = formatTime(entry.end);
728
- content += `${start} --> ${end}\n`;
729
- content += `${entry.text}\n${entry.trans}\n\n`;
730
- });
731
- }
732
-
733
- const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
734
- const url = URL.createObjectURL(blob);
735
- const a = document.createElement('a');
736
- a.href = url;
737
- a.download = `result.${format}`;
738
- document.body.appendChild(a);
739
- a.click();
740
- document.body.removeChild(a);
741
  }
742
 
743
- // 生成字幕并监控字幕合成进度
744
  function generateSubtitle() {
745
- // 检查当前文件是否为视频文件
746
- const validVideoTypes = ['video/mp4', 'video/x-m4v', 'video/*', 'audio/mp4'];
747
- if (!validVideoTypes.includes(window.currentFileType)) {
748
- alert('当前文件不是视频文件,无法合成字幕。');
749
- return;
750
- }
751
-
752
- document.getElementById('subtitleProgress').firstElementChild.style.width = '0%';
753
- document.getElementById('subtitleProgress').firstElementChild.innerText = '0%';
754
-
755
  if (!currentTaskId || asrData.length === 0) {
756
- alert('请确保选择了视频文件并进行了识别');
757
  return;
758
  }
759
 
760
- const postData = {
761
- task_id: currentTaskId,
762
- asr_results: asrData
763
- };
764
 
765
  document.getElementById('generateSubtitleBtn').disabled = true;
766
- document.getElementById('generateSubtitleBtn').innerText = '合成中...';
767
 
768
  const xhr = new XMLHttpRequest();
769
- xhr.open('POST', `${serverUrl}/make_subtitle`, true);
770
- xhr.setRequestHeader('Content-Type', 'application/json');
771
  xhr.onload = function () {
772
- if (xhr.status === 202) {
773
  const response = JSON.parse(xhr.responseText);
774
- monitorSubtitleGeneration(response.task_id);
 
 
 
 
 
 
775
  } else {
776
- alert('合成字幕失败,请重试');
777
  resetGenerateButton();
778
  }
779
  };
780
  xhr.onerror = function () {
781
- alert('合成字幕失败,请重试');
782
  resetGenerateButton();
783
  };
784
- xhr.send(JSON.stringify(postData));
785
  }
786
 
787
- // 监控字幕合成进度
788
  function monitorSubtitleGeneration(taskId) {
789
- console.log('Monitoring subtitle generation for Task ID:', taskId);
790
- let failedRequests = 0; // 计数连续失败的请求
791
- const maxFailedRequests = 10; // 连续失败的最大请求数
792
-
793
  const intervalId = setInterval(function () {
794
  const xhr = new XMLHttpRequest();
795
- xhr.open('GET', `${serverUrl}/get_subtitle_progress/${taskId}`, true);
796
  xhr.onload = function () {
797
-
798
  if (xhr.status === 200) {
799
  const response = JSON.parse(xhr.responseText);
800
- const progress = response.progress;
801
- failedRequests = 0; // 请求成功时重置失败计数
802
-
803
-
804
  if (progress !== undefined) {
805
  updateSubtitleProgress(progress * 100, '正在生成字幕');
806
  }
807
-
808
  if (progress >= 1.0) {
809
  clearInterval(intervalId);
810
- document.getElementById('videoPlayer').src = `${serverUrl}/video/${response.video_url}`;
 
811
  resetGenerateButton();
812
  }
813
  } else {
814
- failedRequests += 1; // 增加失败计数
815
- document.getElementById('logContent').innerText = `请求失败,当前重连次数: ${failedRequests}`;
816
- if (failedRequests >= maxFailedRequests) {
817
- clearInterval(intervalId);
818
- alert('连续请求失败,字幕生成未完成');
819
- resetGenerateButton();
820
- }
821
  }
822
  };
823
  xhr.onerror = function () {
824
- failedRequests += 1; // 增加失败计数
825
- document.getElementById('logContent').innerText = `请求失败,当前重连次数: ${failedRequests}`;
826
- if (failedRequests >= maxFailedRequests) {
827
- clearInterval(intervalId);
828
- alert('连续请求失败,字幕生成未完成');
829
- resetGenerateButton();
830
- }
831
  };
832
  xhr.send();
833
-
834
- }, 1000);
835
  }
836
-
837
- // 更新字幕合成进度
838
  function updateSubtitleProgress(progress, msg) {
839
- const progressBar = document.getElementById('subtitleProgress');
840
- progressBar.firstElementChild.style.width = `${progress}%`;
841
- progressBar.firstElementChild.innerText = `${progress.toFixed(2)}%`;
842
- document.getElementById('logContent').innerText = `进度: ${progress.toFixed(2)}%, 状态: 正在合成含字幕视频,合成完毕将在上面播放器展示`;
 
 
 
 
 
 
 
843
  }
844
 
845
- // 重置生成字幕按钮状态
846
  function resetGenerateButton() {
847
  document.getElementById('generateSubtitleBtn').disabled = false;
848
- document.getElementById('generateSubtitleBtn').innerText = '合成字幕';
849
  }
850
 
851
- // 格式化时间,用于字幕格式化
852
- function formatTime(seconds) {
853
- const hours = Math.floor(seconds / 3600);
854
- const minutes = Math.floor((seconds % 3600) / 60);
855
- const secs = Math.floor(seconds % 60);
856
- const millis = Math.floor((seconds - Math.floor(seconds)) * 1000);
857
- return `${pad(hours)}:${pad(minutes)}:${pad(secs)},${padMillis(millis)}`;
 
 
 
 
 
858
  }
859
 
860
- function pad(value) {
861
- return value.toString().padStart(2, '0');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
862
  }
863
 
864
- function padMillis(value) {
865
- return value.toString().padStart(3, '0');
 
866
  }
867
  </script>
868
 
 
364
  justify-content: space-around;
365
  align-items: center;
366
  }
367
+
368
 
369
  </style>
370
  </head>
 
434
  <button id="exportSrtBtn" class="export-button" onclick="exportAsrData('srt')">导出 SRT</button>
435
  <!-- 修改合成按钮颜色 -->
436
  <button id="generateSubtitleBtn" class="subtitle-button" onclick="generateSubtitle()">合成字幕</button>
437
+ <button id="downloadVideoBtn" style="display: none;" onclick="downloadVideo()">下载字幕视频</button>
438
  </div>
439
  </div>
440
  </div>
 
448
  </footer>
449
 
450
  <script>
451
+ let currentTaskId = null; // 当前任务ID
452
  let asrData = []; // 存储识别结果数据
453
  let serverUrl = null; // 服务器地址
454
+ const chunkSize = 5 * 1024 * 1024; // 分块大小,5MB
455
 
456
  // 监听文件输入更改,预览视频
457
  document.getElementById('videoInput').addEventListener('change', function (event) {
458
  const file = event.target.files[0];
459
+ log('Selected file: ' + file.name);
460
  document.getElementById('uploadBtn').disabled = file.size > 300 * 1024 * 1024;
461
 
462
  const videoPlayer = document.getElementById('videoPlayer');
463
+ videoPlayer.src = URL.createObjectURL(file);
464
+ log('Video URL: ' + videoPlayer.src);
 
465
  });
466
+
467
  // 上传文件并提交任务
468
  function uploadFile() {
469
  const fileInput = document.getElementById('videoInput');
470
  const file = fileInput.files[0];
471
+
472
  if (!file) {
473
  alert('请先选择一个文件');
474
  return;
475
  }
476
+
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  const speakerRecognition = document.getElementById('speakerRecognition').checked;
478
  const englishTranslation = document.getElementById('englishTranslation').checked;
 
 
 
479
  const selectedPipeline = document.querySelector('input[name="pipeline"]:checked').value;
480
+
481
+ log('Speaker Recognition: ' + speakerRecognition + ', English Translation: ' + englishTranslation);
482
+ log('Selected pipeline: ' + selectedPipeline);
483
+
484
  document.getElementById('uploadBtn').disabled = true;
485
+ document.getElementById('uploadBtn').innerText = '正在转写...';
486
+
487
  resetProgress();
 
 
488
  serverUrl = document.getElementById('serverUrlInput').value.trim();
489
+ log('Server URL: ' + serverUrl);
490
+
491
+ initializeTask(file, speakerRecognition, englishTranslation, selectedPipeline);
492
+ }
493
+
494
+ // 初始化任务
495
+ function initializeTask(file, speakerRecognition, englishTranslation, pipeline) {
496
+ log("Initializing task with filename: " + file.name);
497
+ const formData = new FormData();
498
+ formData.append('status', 'init');
499
+ formData.append('filename', file.name);
500
+ formData.append('totalChunks', Math.ceil(file.size / chunkSize));
501
+ formData.append('speakerRecognition', speakerRecognition);
502
+ formData.append('englishTranslation', englishTranslation);
503
+ formData.append('pipeline', pipeline);
504
+
505
  const xhr = new XMLHttpRequest();
506
  xhr.open('POST', `${serverUrl}/submit`, true);
 
507
  xhr.onload = function () {
 
508
  if (xhr.status === 200) {
509
  const response = JSON.parse(xhr.responseText);
510
+ log('Initialization response: ' + JSON.stringify(response));
511
  if (response.code === 0) {
512
+ currentTaskId = response.content;
513
+ log('Task ID: ' + currentTaskId);
514
+ uploadChunks(file); // 开始分块上传
515
  } else {
516
+ alert('初始化失败,请重试');
517
  resetUploadButton();
518
  }
519
  } else {
520
+ alert('初始化失败,请重试');
521
  resetUploadButton();
522
  }
523
  };
524
  xhr.onerror = handleUploadError;
 
 
 
 
 
 
 
525
  xhr.send(formData);
526
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
527
 
528
+ // 上传文件块
529
+ function uploadChunks(file) {
530
+ log("正在上传文件..");
531
+ const totalChunks = Math.ceil(file.size / chunkSize);
532
+ let chunkIndex = 0;
533
+
534
+ function uploadNextChunk() {
535
+ if (chunkIndex >= totalChunks) {
536
+ log("上传完毕,开始转写..");
537
+ submitASRTask();
538
+ return;
539
+ }
540
+
541
+ const start = chunkIndex * chunkSize;
542
+ const end = Math.min(file.size, start + chunkSize);
543
+ const chunk = file.slice(start, end);
544
+
545
+ const formData = new FormData();
546
+ formData.append('status', 'upload');
547
+ formData.append('task_id', currentTaskId);
548
+ formData.append('ChunkId', chunkIndex);
549
+ formData.append('file', chunk);
550
+
551
+ const xhr = new XMLHttpRequest();
552
+ xhr.open('POST', `${serverUrl}/submit`, true);
553
+ xhr.onload = function () {
554
+ if (xhr.status === 200) {
555
+ const response = JSON.parse(xhr.responseText);
556
+ log(`Chunk ${chunkIndex} upload response: ` + JSON.stringify(response));
557
+ if (response.code === 0) {
558
+ updateUploadProgress(chunkIndex, totalChunks);
559
+ chunkIndex++;
560
+ uploadNextChunk(); // 上传下一个块
561
+ } else {
562
+ alert(`第 ${chunkIndex + 1} 块上传失败,请重试`);
563
+ resetUploadButton();
564
+ }
565
+ } else {
566
+ alert(`第 ${chunkIndex + 1} 块上传失败,请重试`);
567
+ resetUploadButton();
568
+ }
569
+ };
570
+ xhr.onerror = handleUploadError;
571
+ xhr.send(formData);
572
  }
573
+
574
+ uploadNextChunk(); // 开始上传第一个块
575
  }
576
 
577
+ // 更新上传进度
578
+ function updateUploadProgress(chunkIndex, totalChunks) {
579
+ const totalProgress = ((chunkIndex + 1) / totalChunks) * 100;
580
+ log('Upload progress: ' + totalProgress.toFixed(2) + '%');
581
+ document.getElementById('uploadProgress').firstElementChild.style.width = `${totalProgress}%`;
582
+ document.getElementById('uploadProgress').firstElementChild.innerText = `${totalProgress.toFixed(2)}%`;
583
  }
584
 
585
+ // 提交 ASR 任务
586
+ function submitASRTask() {
587
+ const formData = new FormData();
588
+ formData.append('status', 'asr');
589
+ formData.append('task_id', currentTaskId);
590
+
591
+ const xhr = new XMLHttpRequest();
592
+ xhr.open('POST', `${serverUrl}/submit`, true);
593
+ xhr.onload = function () {
594
+ if (xhr.status === 200) {
595
+ const response = JSON.parse(xhr.responseText);
596
+ log('ASR submission response: ' + JSON.stringify(response));
597
+ if (response.code === 0) {
598
+ monitorTaskProgress(currentTaskId);
599
+ } else {
600
+ alert('ASR 提交失败,请重试');
601
+ resetUploadButton();
602
+ }
603
+ } else {
604
+ alert('ASR 提交失败,请重试');
605
+ resetUploadButton();
606
+ }
607
+ };
608
+ xhr.onerror = handleUploadError;
609
+ xhr.send(formData);
610
  }
611
 
612
  // 监控任务进度
613
  function monitorTaskProgress(taskId) {
614
+ log('Monitoring task progress for Task ID: ' + taskId);
615
+ let failedRequests = 0;
616
+ const maxFailedRequests = 10;
617
+
618
  const intervalId = setInterval(function () {
619
  const xhr = new XMLHttpRequest();
620
+ xhr.open('GET', `${serverUrl}/task_asr_prgs/${taskId}`, true);
621
  xhr.onload = function () {
 
622
  if (xhr.status === 200) {
623
  const response = JSON.parse(xhr.responseText);
624
+ log('Progress response: ' + JSON.stringify(response));
625
  const status = response.content.status;
626
  const progress = response.content.prgs;
627
  failedRequests = 0;
628
+
629
  if (progress) {
630
+ updateRecognitionProgress((progress.cur / progress.total) * 100, progress.msg);
631
  }
632
+
633
  if (status === "SUCCESS") {
634
  clearInterval(intervalId);
635
  asrData = response.content.result;
636
+ log('Recognition successful, ASR data: ' + JSON.stringify(asrData));
637
  displayResults(asrData);
638
  resetUploadButton();
639
  } else if (status === "FAIL") {
 
642
  resetUploadButton();
643
  }
644
  } else {
645
+ handleProgressError();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
  }
647
  };
648
+ xhr.onerror = handleProgressError;
649
  xhr.send();
650
  }, 2000);
651
  }
652
+
653
+ // 处理进度请求错误
654
+ function handleProgressError() {
655
+ failedRequests++;
656
+ log('请求失败,当前重连次数: ' + failedRequests);
657
+ if (failedRequests >= maxFailedRequests) {
658
+ clearInterval(intervalId);
659
+ alert('连续请求失败,任务未完成');
660
+ resetUploadButton();
661
+ }
662
+ }
663
+
664
  // 更新识别进度
665
  function updateRecognitionProgress(progress, msg) {
666
+ log('Recognition progress: ' + progress + '%, Message: ' + msg);
667
  document.getElementById('recognitionProgress').firstElementChild.style.width = `${progress}%`;
668
  document.getElementById('recognitionProgress').firstElementChild.innerText = `${progress.toFixed(2)}%`;
669
  document.getElementById('logContent').innerText = `进度: ${progress.toFixed(2)}%, 状态: ${msg}`;
 
671
 
672
  // 显示识别结果
673
  function displayResults(results) {
674
+ log('Displaying ASR results');
675
  const asrList = document.getElementById('asrList');
676
  asrList.innerHTML = "";
677
  results.forEach((entry) => {
 
693
  </label>
694
  `;
695
 
696
+ setupASREventHandlers(div, entry);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
697
  asrList.appendChild(div);
698
  });
699
  }
700
 
701
+ // 设置 ASR 事件处理
702
+ function setupASREventHandlers(div, entry) {
703
+ const startInput = div.querySelector('.start-time');
704
+ const endInput = div.querySelector('.end-time');
705
+ const roleInput = div.querySelector('input.role-field');
706
+ const textInput = div.querySelector('input.text-field');
707
+ const transInput = div.querySelector('input.trans-field');
708
+ const dropCheckbox = div.querySelector('input[type="checkbox"]');
709
+ const playButton = div.querySelector('.play-button');
710
+
711
+ startInput.addEventListener('input', () => entry.start = parseFloat(startInput.value));
712
+ endInput.addEventListener('input', () => entry.end = parseFloat(endInput.value));
713
+ roleInput.addEventListener('input', () => entry.role = roleInput.value);
714
+ textInput.addEventListener('input', () => entry.text = textInput.value);
715
+ transInput.addEventListener('input', () => entry.trans = transInput.value);
716
+ dropCheckbox.addEventListener('change', () => entry.drop = dropCheckbox.checked);
717
+
718
+ playButton.addEventListener('click', () => {
719
+ const video = document.getElementById('videoPlayer');
720
+ video.currentTime = entry.start;
721
+ video.play();
722
+ const interval = setInterval(() => {
723
+ if (video.currentTime >= entry.end) {
724
+ video.pause();
725
+ clearInterval(interval);
726
+ }
727
+ }, 100);
728
+ });
 
 
 
729
  }
730
 
731
+ // 生成字幕
732
  function generateSubtitle() {
 
 
 
 
 
 
 
 
 
 
733
  if (!currentTaskId || asrData.length === 0) {
734
+ alert('请确保已选择视频文件并进行了识别');
735
  return;
736
  }
737
 
738
+ const formData = new FormData();
739
+ formData.append('status', "subtitle");
740
+ formData.append('task_id', currentTaskId);
741
+ formData.append('asr_results', JSON.stringify(asrData)); // 将 ASR 数据转为字符串
742
 
743
  document.getElementById('generateSubtitleBtn').disabled = true;
744
+ document.getElementById('generateSubtitleBtn').innerText = '生成中...';
745
 
746
  const xhr = new XMLHttpRequest();
747
+ xhr.open('POST', `${serverUrl}/submit`, true);
 
748
  xhr.onload = function () {
749
+ if (xhr.status === 200) {
750
  const response = JSON.parse(xhr.responseText);
751
+ log('Subtitle generation response: ' + JSON.stringify(response));
752
+ if (response.code === 0) {
753
+ monitorSubtitleGeneration(response.content);
754
+ } else {
755
+ alert('字幕生成失败,请重试');
756
+ resetGenerateButton();
757
+ }
758
  } else {
759
+ alert('字幕生成失败,请重试');
760
  resetGenerateButton();
761
  }
762
  };
763
  xhr.onerror = function () {
764
+ alert('字幕生成失败,请重试');
765
  resetGenerateButton();
766
  };
767
+ xhr.send(formData);
768
  }
769
 
770
+ // 监控字幕生成进度
771
  function monitorSubtitleGeneration(taskId) {
772
+ log('Monitoring subtitle generation for Task ID: ' + taskId);
773
+ let failedRequests = 0;
774
+ const maxFailedRequests = 10;
775
+
776
  const intervalId = setInterval(function () {
777
  const xhr = new XMLHttpRequest();
778
+ xhr.open('GET', `${serverUrl}/task_subtitle_prgs/${taskId}`, true);
779
  xhr.onload = function () {
 
780
  if (xhr.status === 200) {
781
  const response = JSON.parse(xhr.responseText);
782
+ const progress = response.content.progress;
783
+ failedRequests = 0;
784
+
 
785
  if (progress !== undefined) {
786
  updateSubtitleProgress(progress * 100, '正在生成字幕');
787
  }
788
+
789
  if (progress >= 1.0) {
790
  clearInterval(intervalId);
791
+ document.getElementById('videoPlayer').src = `${serverUrl}/video/${taskId}`;
792
+ document.getElementById('downloadVideoBtn').style.display = 'inline'; // Show the download button
793
  resetGenerateButton();
794
  }
795
  } else {
796
+ handleProgressError();
 
 
 
 
 
 
797
  }
798
  };
799
  xhr.onerror = function () {
800
+ handleProgressError();
 
 
 
 
 
 
801
  };
802
  xhr.send();
803
+ }, 2000);
 
804
  }
805
+
806
+ // 更新字幕生成进度
807
  function updateSubtitleProgress(progress, msg) {
808
+ log('Subtitle progress: ' + progress + '%, Message: ' + msg);
809
+ document.getElementById('subtitleProgress').firstElementChild.style.width = `${progress}%`;
810
+ document.getElementById('subtitleProgress').firstElementChild.innerText = `${progress.toFixed(2)}%`;
811
+ document.getElementById('logContent').innerText = `进度: ${progress.toFixed(2)}%, 状态: ${msg}`;
812
+ }
813
+
814
+ // 重置上传按钮状态
815
+ function resetUploadButton() {
816
+ log('Resetting upload button state');
817
+ document.getElementById('uploadBtn').disabled = false;
818
+ document.getElementById('uploadBtn').innerText = '上传并识别';
819
  }
820
 
821
+ // 重置字幕生成按钮状态
822
  function resetGenerateButton() {
823
  document.getElementById('generateSubtitleBtn').disabled = false;
824
+ document.getElementById('generateSubtitleBtn').innerText = '生成字幕';
825
  }
826
 
827
+ // 重置进度条和界面
828
+ function resetProgress() {
829
+ log('Resetting progress bars and UI elements');
830
+ document.getElementById('uploadProgress').firstElementChild.style.width = '0%';
831
+ document.getElementById('uploadProgress').firstElementChild.innerText = '';
832
+ document.getElementById('recognitionProgress').firstElementChild.style.width = '0%';
833
+ document.getElementById('recognitionProgress').firstElementChild.innerText = '';
834
+ document.getElementById('subtitleProgress').firstElementChild.style.width = '0%';
835
+ document.getElementById('subtitleProgress').firstElementChild.innerText = '';
836
+ document.getElementById('asrList').innerHTML = "";
837
+ document.getElementById('logContent').innerText = "";
838
+ document.getElementById('downloadVideoBtn').style.display = 'none';
839
  }
840
 
841
+ // 下载视频
842
+ function downloadVideo() {
843
+ if (!currentTaskId) {
844
+ alert('请确保已生成字幕视频');
845
+ return;
846
+ }
847
+
848
+ const xhr = new XMLHttpRequest();
849
+ xhr.open('GET', `${serverUrl}/url/${currentTaskId}`, true);
850
+ xhr.onload = function () {
851
+ if (xhr.status === 200) {
852
+ const response = JSON.parse(xhr.responseText);
853
+ if (response.code === 0) {
854
+ const videoUrl = response.content.url;
855
+ const a = document.createElement('a');
856
+ a.href = `${serverUrl}/${videoUrl}`;
857
+ a.download = `subtitle_video_${currentTaskId}.mp4`; // Specify the filename
858
+ document.body.appendChild(a);
859
+ a.click();
860
+ document.body.removeChild(a);
861
+ } else {
862
+ alert('下载链接生成失败,请重试');
863
+ }
864
+ } else {
865
+ alert('下载失败,请重试');
866
+ }
867
+ };
868
+ xhr.onerror = function () {
869
+ alert('下载请求出错,请重试');
870
+ };
871
+ xhr.send();
872
+ }
873
+
874
+ // 错误处理
875
+ function handleUploadError() {
876
+ log('Upload error occurred');
877
+ alert('上传失败,请重试');
878
+ resetUploadButton();
879
  }
880
 
881
+ function log(msg) {
882
+ document.getElementById('logContent').innerText = msg;
883
+ console.log(msg);
884
  }
885
  </script>
886