同步

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Threading;

namespace AudioPlayerApp
{
    public partial class MainWindow : Window
    {
        private DispatcherTimer _subtitleTimer;
        private List<Subtitle> _subtitles;
        private List<Subtitle> _subtitlesEn;
        private TextRange _textRange;
        private TextRange _textRangeEn;
        private HashSet<string> _outputtedSubtitles; // 用于存储已输出的字幕文本
        private HashSet<string> _outputtedSubtitlesEn; // 用于存储已输出的字幕文本

        public MainWindow()
        {
            InitializeComponent();
            InitializeApp(); // 初始化应用程序
        }

        private void InitializeApp()
        {
            _subtitles = LoadSubtitles("test_cn.srt");
            _subtitlesEn = LoadSubtitles("test_en.srt");

            SetRichTextBoxContent(_subtitles, ref _textRange, TextDisplay);
            SetRichTextBoxContent(_subtitlesEn, ref _textRangeEn, TextDisplayEn);

            InitializeTimer();
            InitializeOutputtedSubtitles();
        }

        private List<Subtitle> LoadSubtitles(string filePath)
        {
            var subtitles = new List<Subtitle>();
            var lines = File.ReadAllLines(filePath);

            for (int i = 0; i < lines.Length; i++)
            {
                if (int.TryParse(lines[i], out _)) // Skip index line
                {
                    i++;
                    var timeLine = lines[i].Split(new[] { " --> " }, StringSplitOptions.None);
                    var startTime = TimeSpan.Parse(timeLine[0].Replace(',', '.'));
                    var endTime = TimeSpan.Parse(timeLine[1].Replace(',', '.'));
                    i++;
                    var text = lines[i]; // Add subtitle text
                    subtitles.Add(new Subtitle { StartTime = startTime, EndTime = endTime, Text = text });
                }
            }

            return subtitles;
        }

        private void SetRichTextBoxContent(List<Subtitle> subtitles, ref TextRange textRange, RichTextBox richTextBox)
        {
            string content = string.Join("\r", subtitles.Select(x => x.Text).ToArray());
            textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
            textRange.Text = content;
        }

        private void InitializeTimer()
        {
            _subtitleTimer = new DispatcherTimer
            {
                Interval = TimeSpan.FromMilliseconds(100)
            };
            _subtitleTimer.Tick += SubtitleTimer_Tick;
        }

        private void InitializeOutputtedSubtitles()
        {
            _outputtedSubtitles = new HashSet<string>();
            _outputtedSubtitlesEn = new HashSet<string>();
        }

        private void SubtitleTimer_Tick(object sender, EventArgs e)
        {
            if (MediaPlayer.NaturalDuration.HasTimeSpan)
            {
                var currentTime = MediaPlayer.Position;
                ProgressSlider.Value = MediaPlayer.Position.TotalSeconds;
                UpdateHighlightedSubtitles(currentTime);
            }
        }

    

        private void UpdateHighlightedSubtitles(TimeSpan currentTime)
        {
            UpdateHighlightedSubtitle(currentTime, _subtitles, _textRange, ClearHighlight,scrollViewer);
            UpdateHighlightedSubtitle(currentTime,_subtitlesEn, _textRangeEn, ClearHighlight, scrollViewerEn);
        }

        private void UpdateHighlightedSubtitle(TimeSpan currentTime, List<Subtitle> subtitlesList, TextRange textRange
            , Action<TextRange> clearHighlightAction
            , ScrollViewer scrollViewer
            )
        {
           
            var currentSubtitle = subtitlesList.Find(s => currentTime >= s.StartTime && currentTime <= s.EndTime);

            if (currentSubtitle != null)
            {
                HighlightSpecificText(currentSubtitle.Text, textRange,scrollViewer);
            }
            else
            {
                clearHighlightAction(textRange); // 如果没有字幕,清除高亮
            }
        }

        private void HighlightSpecificText(string textToHighlight, TextRange textRange, ScrollViewer scrollViewer)
        {
            ClearHighlight(textRange); // 清除之前的高亮
            if (string.IsNullOrEmpty(textToHighlight))
                return;

            string fullText = textRange.Text;
            int startIndex = 0;

            while (startIndex < fullText.Length)
            {
                startIndex = fullText.IndexOf(textToHighlight, startIndex, StringComparison.OrdinalIgnoreCase);
                if (startIndex < 0)
                    break;

                TextPointer startPointer = textRange.Start.GetPositionAtOffset(startIndex);
                TextPointer endPointer = startPointer.GetPositionAtOffset(textToHighlight.Length);

                TextRange highlightRange = new TextRange(startPointer, endPointer);
                highlightRange.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Yellow);
                highlightRange.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);

                // 自动滚动到高亮文本的位置
                ScrollToHighlight(startPointer, scrollViewer);

                startIndex += textToHighlight.Length;
            }
        }

        private void ScrollToHighlight(TextPointer startPointer, ScrollViewer scrollViewer)
        {

            // 获取高亮文本的可视位置
            Rect rect = startPointer.GetCharacterRect(LogicalDirection.Forward);
            if (rect != Rect.Empty)
            {
                // 计算滚动偏移量
                double verticalOffset = rect.Top - (scrollViewer.ViewportHeight / 2);
                if (verticalOffset < 0)
                {
                    verticalOffset = 0;
                }

                // 滚动到目标位置
                scrollViewer.ScrollToVerticalOffset(verticalOffset);
            }
        }
        private void ClearHighlight(TextRange textRange)
        {
            TextRange fullTextRange = new TextRange(textRange.Start, textRange.End);
            fullTextRange.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Transparent);
            fullTextRange.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
        }

        private void ProgressSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (MediaPlayer.NaturalDuration.HasTimeSpan)
            {
                UpdateMediaPosition();
                var currentTime = MediaPlayer.Position;
                UpdateHighlightedSubtitles(currentTime);
            }
        }

        private void UpdateMediaPosition()
        {
            if (MediaPlayer.NaturalDuration.TimeSpan.TotalSeconds > 0)
            {
                MediaPlayer.Position = TimeSpan.FromSeconds(ProgressSlider.Value);
                //Debug.WriteLine($"位置:" + MediaPlayer.Position);
            }
        }

        private void MediaPlayer_MediaOpened(object sender, RoutedEventArgs e)
        {
            if (MediaPlayer.NaturalDuration.HasTimeSpan)
            {
                ProgressSlider.Maximum = MediaPlayer.NaturalDuration.TimeSpan.TotalSeconds;
            }
            _subtitleTimer.Start();
        }

        private void PlayButton_Click(object sender, RoutedEventArgs e)
        {
            MediaPlayer.Play();
        }

        private void PauseButton_Click(object sender, RoutedEventArgs e)
        {
            MediaPlayer.Pause();
        }

        private void StopButton_Click(object sender, RoutedEventArgs e)
        {
            ResetToInitialState(); // 重置到初始状态
        }

        private void MediaPlayer_MediaEnded(object sender, EventArgs e)
        {
            Debug.WriteLine("音频播放完毕");
            ResetToInitialState(); // 重置到初始状态
        }

        private void ResetToInitialState()
        {
            MediaPlayer.Stop();
            _subtitleTimer.Stop();
            ProgressSlider.Value = 0;
            ClearHighlight(_textRange);
            ClearHighlight(_textRangeEn);
            scrollViewer.ScrollToHome();
            scrollViewerEn.ScrollToHome();
            _outputtedSubtitles.Clear();
            _outputtedSubtitlesEn.Clear();
        }

        private class Subtitle
        {
            public TimeSpan StartTime { get; set; }
            public TimeSpan EndTime { get; set; }
            public string Text { get; set; }
        }
    }
}

  

posted on 2025-02-21 15:36  詠吥誩棄  阅读(10)  评论(0)    收藏  举报