UWP实现第二字幕并且跟随系统的设置
阅读原文时间:2023年07月10日阅读:1

话不多说,先看一下最终效果

系统设置默认

在系统设置里面更改字幕的显示效果

需求

要求播放器可以显示第二字幕,类似旁白的文字解释。比如片中出现了一个专业术语,这个时候观众可能有些疑惑。所以需要在屏幕上显示这个专业术语的解释。

1. 解析字幕文件

第二字幕也是字幕文件,需要找专门的类进行解析。而第一字幕则不需要这么麻烦,播放器会自动处理并显示的。

srt字幕文件一般格式如下

  • 字幕序号
  • 字幕显示的起始时间 --> 结束时间
  • 字幕内容(可多行)
  • 空白行(表示本字幕段的结束)

字母序号并不起任何实际的作用,只是用来标明而已,解析的时候用不到

首先加载一个字幕文件,我把文件放在Assets文件夹里面了。

var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/secondCC.srt"));
if (file == null)
return;

Stream stream = await file.OpenStreamForReadAsync();

var parser = new SubParser();

SubtitleList = parser.ParseStream(await file.OpenStreamForReadAsync(), encoding, mostLikelyFormat);

代码通过读取srt文件,把内容都存在一个List,

SubtitleItem的model定义为

    public int Number { get; set; }

    public int StartTime { get; set; }

    public int EndTime { get; set; }

    public List<string> Lines { get; set; }

2. 获取系统字幕设置

打开Windows设置——轻松使用——隐藏式字幕

默认情况下所有的设置都是默认,当然你可以自己更改,不过这个将对你的第一字幕产生影响。而我们要达到的效果是同时更改第二字幕的效果。

比如获取字体颜色

        if (Windows.Media.ClosedCaptioning.ClosedCaptionProperties.FontColor != Windows.Media.ClosedCaptioning.ClosedCaptionColor.Default)  
            richtextblock.Foreground = new SolidColorBrush(Windows.Media.ClosedCaptioning.ClosedCaptionProperties.ComputedFontColor);  
        else  
            richtextblock.Foreground = new SolidColorBrush(Colors.White);

字体大小

            //系统默认不返回字体的具体大小,而是一个愚蠢的百分比。官方解释说具体的字体大小会根据窗体大小等一系列因素决定,但是又不给你说怎么个计算方法  
            //所以这里就先给一个初始值。如果你知道怎么计算或者获取最终大小,请create PR。  
            double defaultSize = ;  
            switch (Windows.Media.ClosedCaptioning.ClosedCaptionProperties.FontSize)  
            {  
                case Windows.Media.ClosedCaptioning.ClosedCaptionSize.FiftyPercent:  
                    richtextblock.FontSize = defaultSize \* .;  
                    break;  
                case Windows.Media.ClosedCaptioning.ClosedCaptionSize.OneHundredPercent:  
                    richtextblock.FontSize = defaultSize \* ;  
                    break;  
                case Windows.Media.ClosedCaptioning.ClosedCaptionSize.OneHundredFiftyPercent:  
                    richtextblock.FontSize = defaultSize \* 1.5;  
                    break;  
                case Windows.Media.ClosedCaptioning.ClosedCaptionSize.TwoHundredPercent:  
                    richtextblock.FontSize = defaultSize \* 2.0;  
                    break;  
                default:  
                    richtextblock.FontSize = defaultSize \* 1.0;  
                    break;  
            }

背景色

if (Windows.Media.ClosedCaptioning.ClosedCaptionProperties.BackgroundColor != Windows.Media.ClosedCaptioning.ClosedCaptionColor.Default)
{
border.Background = new SolidColorBrush(Windows.Media.ClosedCaptioning.ClosedCaptionProperties.ComputedBackgroundColor);

            Color backColor = Windows.Media.ClosedCaptioning.ClosedCaptionProperties.ComputedBackgroundColor;  
            switch (Windows.Media.ClosedCaptioning.ClosedCaptionProperties.BackgroundOpacity)  
            {  
                case Windows.Media.ClosedCaptioning.ClosedCaptionOpacity.OneHundredPercent:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));//.Opacity = 1.0;  
                    break;  
                case Windows.Media.ClosedCaptioning.ClosedCaptionOpacity.SeventyFivePercent:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));  
                    break;  
                case Windows.Media.ClosedCaptioning.ClosedCaptionOpacity.TwentyFivePercent:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));  
                    break;  
                case Windows.Media.ClosedCaptioning.ClosedCaptionOpacity.ZeroPercent:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));  
                    break;  
                default:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));  
                    break;  
            }  
        }  
        else  
        {  
            Color backColor = Colors.Black;  
            switch (Windows.Media.ClosedCaptioning.ClosedCaptionProperties.BackgroundOpacity)  
            {  
                case Windows.Media.ClosedCaptioning.ClosedCaptionOpacity.OneHundredPercent:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));//.Opacity = 1.0;  
                    break;  
                case Windows.Media.ClosedCaptioning.ClosedCaptionOpacity.SeventyFivePercent:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));  
                    break;  
                case Windows.Media.ClosedCaptioning.ClosedCaptionOpacity.TwentyFivePercent:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));  
                    break;  
                case Windows.Media.ClosedCaptioning.ClosedCaptionOpacity.ZeroPercent:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));  
                    break;  
                default:  
                    border.Background = new SolidColorBrush(Color.FromArgb(, backColor.R, backColor.G, backColor.B));  
                    break;  
            }  
        }

3. 显示第二字幕

在timer里面,我们需要实时更新字幕内容。

如果字幕文件有自定义的样式,那么最终的样式将会呗保留,而不受系统影响。

try
{
if (SubtitleList != null && SubtitleList.Any())
{
var v = (from item in SubtitleList
where item != null
&& item.StartTime + seekDouble <= MyPlayer.MediaPlayer.PlaybackSession.Position.TotalMilliseconds && item.EndTime + seekDouble >= MyPlayer.MediaPlayer.PlaybackSession.Position.TotalMilliseconds
orderby item descending
select item).FirstOrDefault();
CurrentSubtitleItem = v;
if (v != null)
{
richtextblock.Blocks.Clear();

                    Paragraph myParagraph = new Paragraph();  
                    int nextParagraph = ;  
                    string paragraph = "";  
                    foreach (string item in v.Lines)  
                    {  
                        paragraph += item.Trim().ToString() + "\\r\\n";  
                        if (GetRun(item) != null)  
                        {  
                            myParagraph.Inlines.Add(GetRun(item.Trim()));  
                            try  
                            {  
                                if (v.Lines\[nextParagraph\] != null)  
                                {  
                                    myParagraph.Inlines.Add(new LineBreak());  
                                }  
                            }  
                            catch (Exception ex) { Debug.WriteLine("nextParagraph ex: " + ex.Message); }  
                        }  
                        nextParagraph++;  
                    }  
                    //Run run = new Run();  
                    //run.Text = paragraph.Trim();  
                    //myParagraph.Inlines.Add(run);  
                    richtextblock.Blocks.Add(myParagraph);  
                    border.Visibility = Visibility.Visible;  
                }  
                else  
                {  
                    border.Visibility = Visibility.Collapsed;  
                    richtextblock.Blocks.Clear();  
                }  
            }  
            else  
                richtextblock.Blocks.Clear();  
        }  
        catch (Exception ex) { Debug.WriteLine("mediaPlayer\_PositionChanged ex: " + ex.Message); }

比如字幕文件有

::, --> ::,
::,000When a powerful desire indwells in things touched by mortal souls,When a powerful desire indwells in things touched by mortal souls,
颜色
字体斜体
字体下加划线

换行
字体加粗
::, first line ends

::, --> ::,
::, they become goblins.

那么最终的展示效果为:

紫色效果是系统设置,而颜色在字幕里面内置了红色,那么它将不会受系统影响。

4. 源代码

本代码已经开源,获取请点击,如果可以的话,请点击右上角Star

https://github.com/hupo376787/UWPSecondSubtitle

5. 特别鸣谢

开源动画组织:bbb_sunflower_1080p_60fps_normal.mp4/elephantsdream-clip-h264_sd-aac_eng-aac_spa-aac_eng_commentary-srt_eng-srt_por-srt_swe.mkv

本文的字幕文件解析代码参考了开源代码 ramtinakhttps://github.com/ramtinak/UltraPlayer

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章