win11实时字幕,显示到在线视频

10 篇文章 0 订阅
7 篇文章 0 订阅

妈妈再也不用担心我找不到字幕了


win11自带了一个实时字幕,识别效果还不错

于是我就有了个想法,抓取文本并,通过网络本地调用,然后实时加载到在线视频上。

说干就干,一开始我尝试使用node,flutter都失败了。

于是我就只能被迫使用了我从未用过的C#

万万没想到,我的第一个C#程序不是helloworld

using System;
using System.Collections.Generic;
using System.Windows.Automation;

class Program
{
    static void Main(string[] args)
    {
        string windowTitle;
        if (args.Length == 0)
        {
            windowTitle = "实时辅助字幕";
            Console.WriteLine("Usage: uiget.exe \"Window Title\"");
            //return;
        }
        else
        {

        windowTitle = args[0];
        }

        // 查找具有特定标题的窗口
        AutomationElement window = FindWindowByTitle(windowTitle);

        if (window != null)
        {

            List<string> texts = new List<string>();
            WalkAutomationTreeAndCollectTexts(window, texts);
            Console.WriteLine(texts[0]);
        }
        else
        {
            Console.WriteLine("");
        }
    }

    static AutomationElement FindWindowByTitle(string title)
    {
        var condition = new PropertyCondition(AutomationElement.NameProperty, title);
        return AutomationElement.RootElement.FindFirst(TreeScope.Children, condition);
    }

    static void WalkAutomationTree(AutomationElement rootElement)
    {
        var condition = Condition.TrueCondition; // 查找所有子节点
        var treeWalker = new TreeWalker(condition);
        WalkAutomationTree(treeWalker, rootElement, 0);
    }

    // 递归遍历UI自动化树
    static void WalkAutomationTree(TreeWalker walker, AutomationElement element, int indent)
    {
        string indentString = new string(' ', indent);

        // 尝试使用ObjectModel获取文本
        string elementText = GetTextFromElement(element);
        Console.WriteLine($"{indentString}{element.Current.ControlType.ProgrammaticName} - Name: {element.Current.Name}, Text: {elementText}");

        AutomationElement child = walker.GetFirstChild(element);
        while (child != null)
        {
            WalkAutomationTree(walker, child, indent + 2); // 增加缩进
            child = walker.GetNextSibling(child); // 移动到下一个兄弟元素
        }
    }

    // 从元素获取文本的尝试
    static string GetTextFromElement(AutomationElement element)
    {
        try
        {
            object patternObj;
            if (element.TryGetCurrentPattern(TextPattern.Pattern, out patternObj))
            {
                var textPattern = (TextPattern)patternObj;
                return textPattern.DocumentRange.GetText(-1).TrimEnd('\r'); // 获取所有文本并删除尾随的回车符
            }
            else if (element.TryGetCurrentPattern(ValuePattern.Pattern, out patternObj))
            {
                var valuePattern = (ValuePattern)patternObj;
                return valuePattern.Current.Value;
            }
            else
            {
                // 没有找到TextPattern或ValuePattern
                return string.Empty;
            }
        }
        catch (ElementNotAvailableException)
        {
            return string.Empty;
        }
    }
    static void WalkAutomationTreeAndCollectTexts(AutomationElement element, List<string> texts)
    {
        var treeWalker = TreeWalker.RawViewWalker;
        CollectTextsRecursively(treeWalker, element, texts);
    }

    static void CollectTextsRecursively(TreeWalker walker, AutomationElement element, List<string> texts)
    {
        string elementText = GetTextFromElement(element);
        if (!string.IsNullOrEmpty(elementText))
        {
            texts.Add(elementText);
        }

        AutomationElement child = walker.GetFirstChild(element);
        while (child != null)
        {
            CollectTextsRecursively(walker, child, texts);
            child = walker.GetNextSibling(child);
        }
    }
}

然后再使用我熟悉的nodejs调用

const { exec } = require('child_process');
const iconv = require('iconv-lite');

function getUITextByTitle(title, callback) {
  exec(`uiget.exe "${title}"`, { encoding: 'buffer' }, (error, stdoutBuffer, stderrBuffer) => {
    console.log('当前Node.js默认编码:', Buffer.from('').constructor.name);
    if (error) {
      return callback(error, null);
    }
    if (stderrBuffer.length) {
      // 注意:这里假设标准错误流(stderr)也是 GB2312 编码
      return callback(new Error(iconv.decode(stderrBuffer, 'GB2312')), null);
    }

    try {
      // 使用iconv-lite将Buffer从GB2312转码为UTF-8字符串
      const stdoutText = iconv.decode(stdoutBuffer, 'GB2312');
      callback(null, stdoutText);
    } catch (parseError) {
      callback(parseError, null);
    }
  });
}

大功告成,之后就是封装为route,用express代理一下就好了
 

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
视频字母合并 视频合并 MKVtoolnix4.0( 除wmv) MKV字幕提取与封装软件   mkvtoolnix (又叫Matroska toolkit),是一套功能强大的mkv(Matroska)格式制作和处理的工具,支持将多种视频、音频、字幕等格式封装成mkv格式。Mkvtoolnix 中包含了一个图形界面程序mmg.exe,这样使得制作mkv更简单和直观。还包含 MKVextractGUI.exe程序,可以提取 MKV 文件里面的音视频和字幕文件。 Mkvtoolnix是目前功能最齐全的Matroska合成器,除了WMV和MPEG-1/2之外,它几乎能将所有的媒体合成到MKV中去。 制作发行: DarkDudae and Affar   运行环境:Winxp/vista/win7/2000/2003 MKV封装风头日盛,尤其是那些多声轨、多字幕的高清MKV大片更是倍受青睐,丝丝入扣的影像和逼真震撼的音响让人流连忘返,这也是高清MKV最大的卖点。但不少读者在播放高清MKV及格式转换等方面遇到了不少问题,例如播放迟滞、音画不同步及字幕不匹配等。MKV的葫芦里究竟卖的什么药呢? 播放时资源紧张导致解码迟滞,应尽量避免在播放高清影片时执行大型程序或其他占用内存较大的程序。MKV文件本身有问题,例如MKV封装错误等,这种情况比较特殊,要利用MKV合成工具MKVtoolnix的MKVmerge(mmg)重新封装MKV文件方可解决。 很多高清MKV下载网站采取分段处理的方式,这使得我们看电影时不能够“一气呵成”,那么有什么办法可以将分段的部分拼接起来,又不影响观看质量呢?菜鸟学院今天就为各位视频菜菜带来利用MKVtoolnix这款小工具将多个MKV格式的影片合并在一起的方法。 说明   1、安装及运行   Mkvtoolnix解压之后,还要将Mkvtoolnix Runtime Package也一并解压到Mkvtoolnix所在的目录中,否则它是无法运行的。Mkvtoolnix的主程序mkvmerge.exe是命令行程序,不过这个软件包中还提供了一个GUI外壳程序mmg.exe,可运行它来对mkvmerge.exe进行操作。   2、文件导入   运行mmg.exe后,会弹出软件的图形界面,首先选择“Input”选择卡,点击上部“Input files”处的“add”按钮,将要合并的视频、音频、字幕文件一一添加到文件列表中,Mkvtoolnix功能的强大主要体现在能导入的格式上,除了MPEG视频外,几乎所有的主流音、视频格式它都能容纳,包括OGM和MKV格式本身!   3、轨道设置   如果视频中已经包括有音频,它还可以选择是保留还是不保留该音频!如果要去掉原有的音频,先在文件列表中选中该视频文件,然后在下面的Tracks列表中将音轨前的勾去掉即可。这样的功能要比OGM方便得多! 所有的轨道都可以加上语言类型、标题、作者等标示,先选定某个轨道,然后在下面“Track Options”处的“Language”下拉列表中进行选择。在字幕或声音不同步的情况下,还可设置声轨和字幕播放的延时时间,可将延时数值填入Delay后的文字框(单位为毫秒)。   4、文件分割    如果想将合并好的MKV文件刻入光盘,而最终合并好的文件可能超过光盘的容量的话,你可以对文件进行分割。选择“Global(全局)”选项卡,在其中的“Split(分割)”栏中勾选“Enable splitting(进行分割)”,分割有两种方式:“by size(按文件尺寸)”、“by time(按时间)”,这里当然应该按尺寸,具体的尺寸可从后面的下拉列表中选择。   5、输出   界面中的其它选项卡都是无关紧要的,可以不管。最后,在下面的“Output filename(输出文件名)”处设置输出文件的路径及名称后,点击“Start Muxing(开始合并)”按钮输出MKV文件。另外,Mkvtoolnix也可用于分离MKV文件,只要将MKV文件导入,再将每个码流单独命名输出就形了。 注意   1、目前mkvtoolnix支持大部分的视频、音频和字幕格式的封装,但部分格式并不支持,比如asf、wmv等格式,需要asf2mkv recorder的辅助才能进行MKV的封装;安装运行asf2mkv recorder,在软件窗口的地址栏中输入源文件的完整路径(也可复制),然后单击“Record!”按钮,会弹出另存为对话框,在其中设置好MKV文件保存的路径及名称后即可输出MKV文件。    2、新版的mkvtoolnix增加了append追加功能,可以追加视频、音频和字幕,但必须保证格式一致才可以,比如追加rmvb视频,就必须保证音频编码格式和分辨率都一致才可以追加;   3、点击Tracks中的相应项目,然后在Track options中进行设置。对于视频、音频和图形字幕一般可以不设置,默认即可;对于文本字幕需要设置一下该字幕在菜单中的语言显示,以方便播放时进行识别和选择;注意字幕语言如果是中文,language选择chi(chinese),而不要选择zho(chinese),因为选择后者,字幕菜单显示不了chinese字样,只显示undetermined(原因不明)   4、如果字幕或音频有声音延迟,可以在Delay中定义;   5、Track name可以自定义菜单的显示内容,不过这个选项好像只对音频有效,对字幕无效,字幕名字还是要到language里面去指定;   6、如果封装的文件比较大,可以进行分割,方法是切换到Global选卡,在split中指定文件分割的方式;另外这里还可以指定MKV的标题或章节的名称,也可以不填。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值