sonygod commited on
Commit
cfea4fd
·
1 Parent(s): cac2dd6

完美版本

Browse files
Files changed (1) hide show
  1. youtube_sub.js +43 -27
youtube_sub.js CHANGED
@@ -361,7 +361,7 @@ GM_addStyle(`
361
  if (!data?.events) {
362
  throw new Error('Invalid subtitle data format');
363
  }
364
- debugger;
365
  const subtitles = data.events
366
  .filter(event => event.segs && event.tStartMs !== undefined)
367
  .map(event => ({
@@ -636,31 +636,47 @@ GM_addStyle(`
636
  }
637
 
638
 
 
639
  setupVideoTimeUpdate() {
640
  let rafId = null;
641
- const updateThreshold = 16; // ~60fps
642
  let lastUpdate = 0;
643
-
644
- const findSubtitleIndex = (time, subtitles) => {
645
- // Binary search for faster lookup
646
- let start = 0;
647
- let end = subtitles.length - 1;
648
-
649
- while (start <= end) {
650
- const mid = Math.floor((start + end) / 2);
651
- const sub = subtitles[mid];
652
-
653
- if (time >= sub.startTime && time <= sub.endTime) {
654
- return mid;
 
655
  }
 
 
 
656
 
657
- if (time < sub.startTime) {
658
- end = mid - 1;
659
- } else {
660
- start = mid + 1;
661
- }
 
 
 
 
 
 
 
 
 
 
662
  }
663
- return -1;
 
664
  };
665
 
666
  const handleTimeUpdate = (video) => {
@@ -675,28 +691,28 @@ GM_addStyle(`
675
  const subtitles = this.currentTab === 'chinese' ?
676
  this.subtitles.chinese : this.subtitles.english;
677
 
678
- const newIndex = findSubtitleIndex(currentTime, subtitles);
679
- if (newIndex === this.subtitleIndex) {
680
  rafId = requestAnimationFrame(() => handleTimeUpdate(video));
681
  return;
682
  }
683
 
684
- this.subtitleIndex = newIndex;
685
  const lines = this.container.querySelectorAll('.subtitle-line');
686
-
687
  lines.forEach(line => {
688
  const lineIndex = parseInt(line.dataset.index);
689
  const isActive = lineIndex === newIndex;
690
 
691
  line.classList.toggle('active', isActive);
692
- if (isActive) {
 
693
  line.scrollIntoView({
694
  block: 'center',
695
- behavior: 'auto'
696
  });
697
  }
698
  });
699
 
 
700
  rafId = requestAnimationFrame(() => handleTimeUpdate(video));
701
  };
702
 
@@ -760,7 +776,7 @@ GM_addStyle(`
760
 
761
  //enter debug mode
762
 
763
- debugger;
764
 
765
  // 3. Load subtitle data
766
  for (const track of tracks) {
 
361
  if (!data?.events) {
362
  throw new Error('Invalid subtitle data format');
363
  }
364
+ //debugger;
365
  const subtitles = data.events
366
  .filter(event => event.segs && event.tStartMs !== undefined)
367
  .map(event => ({
 
636
  }
637
 
638
 
639
+
640
  setupVideoTimeUpdate() {
641
  let rafId = null;
642
+ const updateThreshold = 16;
643
  let lastUpdate = 0;
644
+ const TRANSITION_BUFFER = 0.1; // 100ms buffer
645
+ let lastActiveIndex = -1;
646
+
647
+ const findActiveSubtitle = (time, subtitles) => {
648
+ // Find all potentially active subtitles
649
+ const active = [];
650
+
651
+ for (let i = 0; i < subtitles.length; i++) {
652
+ const sub = subtitles[i];
653
+ // Add buffer for smoother transitions
654
+ if (time >= (sub.startTime - TRANSITION_BUFFER) &&
655
+ time <= (sub.endTime + TRANSITION_BUFFER)) {
656
+ active.push({ index: i, sub });
657
  }
658
+ // Early exit if we're past the current time
659
+ if (sub.startTime > time + 1) break;
660
+ }
661
 
662
+ if (active.length === 0) return -1;
663
+
664
+ // If multiple subtitles are active, choose the most relevant one
665
+ if (active.length > 1) {
666
+ // Prefer subtitle that has just started
667
+ const justStarted = active.find(({ sub }) =>
668
+ Math.abs(time - sub.startTime) < TRANSITION_BUFFER);
669
+ if (justStarted) return justStarted.index;
670
+
671
+ // Otherwise use the one with the closest start time
672
+ return active.reduce((prev, curr) => {
673
+ const prevDiff = Math.abs(time - prev.sub.startTime);
674
+ const currDiff = Math.abs(time - curr.sub.startTime);
675
+ return currDiff < prevDiff ? curr : prev;
676
+ }).index;
677
  }
678
+
679
+ return active[0].index;
680
  };
681
 
682
  const handleTimeUpdate = (video) => {
 
691
  const subtitles = this.currentTab === 'chinese' ?
692
  this.subtitles.chinese : this.subtitles.english;
693
 
694
+ const newIndex = findActiveSubtitle(currentTime, subtitles);
695
+ if (newIndex === lastActiveIndex) {
696
  rafId = requestAnimationFrame(() => handleTimeUpdate(video));
697
  return;
698
  }
699
 
 
700
  const lines = this.container.querySelectorAll('.subtitle-line');
 
701
  lines.forEach(line => {
702
  const lineIndex = parseInt(line.dataset.index);
703
  const isActive = lineIndex === newIndex;
704
 
705
  line.classList.toggle('active', isActive);
706
+ if (isActive && lineIndex !== lastActiveIndex) {
707
+ // Smooth scroll for new active subtitle
708
  line.scrollIntoView({
709
  block: 'center',
710
+ behavior: 'smooth'
711
  });
712
  }
713
  });
714
 
715
+ lastActiveIndex = newIndex;
716
  rafId = requestAnimationFrame(() => handleTimeUpdate(video));
717
  };
718
 
 
776
 
777
  //enter debug mode
778
 
779
+ //debugger;
780
 
781
  // 3. Load subtitle data
782
  for (const track of tracks) {