让手刹编码器工作

问题描述 投票:0回答:3

我无法让 Handbrake 在 C# 中为我工作。它不断抛出错误“值不能为空”。 。正如您在下面的屏幕截图中看到的,我根据我所知道的尝试了一些方法。我非常感谢您的任何指导来帮助我完成这项工作。

Handbrake Encoder error

到目前为止我所尝试的(点与显示的错误无关。仅供参考):

  1. 在我的电脑上安装了手刹
  2. 添加了对 HandBrakeInterop.dll 的引用
  3. 将所有其他所需的 dll 复制到我的调试文件夹中,甚至尝试将它们添加为引用
  4. 尝试从 x86/x64 更改调试版本

我哪里没有走上正轨?

这是我的代码:

      HandBrake.Interop.HandBrakeInstance objHb = new HandBrake.Interop.HandBrakeInstance();
    HandBrake.Interop.Model.EncodeJob objJob = new HandBrake.Interop.Model.EncodeJob();
    objJob.SourceType = HandBrake.Interop.Model.SourceType.File;
    EncodingProfile objProfile = new EncodingProfile();
    objProfile.OutputFormat = Container.Mp4;
    objProfile.VideoEncodeRateType = VideoEncodeRateType.ConstantQuality;
    objProfile.IPod5GSupport = true;
    objProfile.PreferredExtension = OutputExtension.Mp4;
   // objJob.EncodingProfile = objProfile;
    objJob.SourcePath = AppDomain.CurrentDomain.BaseDirectory + "1.flv";
    objJob.OutputPath = AppDomain.CurrentDomain.BaseDirectory + "1.mp4";
    //objHb.Titles.Add(new HandBrake.Interop.SourceData.Title());

    XmlSerializer objSerializer = new XmlSerializer(typeof(EncodingProfile));


   MemoryStream mem=new MemoryStream(File.ReadAllBytes(AppDomain.CurrentDomain.BaseDirectory + "normal.xml"));
 var objPresetFromFile =  objSerializer.Deserialize(mem) as EncodingProfile;
 objJob.EncodingProfile = objPresetFromFile;
    objJob.UseDefaultChapterNames = true;
   // objJob.Title = 1;



    //HandBrake.Interop.Model.Encoders
    objHb.EncodeProgress += objHb_EncodeProgress;
    objHb.EncodeCompleted += objHb_EncodeCompleted;
    HandBrake.ApplicationServices.Parsing.Title title = new HandBrake.ApplicationServices.Parsing.Title();// new HandBrake.Interop.SourceData.Title();
    objHb.Initialize(5);
    //objHb.Titles = new System.Collections.Generic.List<HandBrake.Interop.SourceData.Title>();
    objHb.StartScan(AppDomain.CurrentDomain.BaseDirectory + "1.flv", 0);
    objJob.SourceType = HandBrake.Interop.Model.SourceType.File;
    objJob.RangeType = HandBrake.Interop.Model.VideoRangeType.Frames;

    objHb.StartEncode(objJob);

    Console.ReadLine();

编辑:根据要求,这里有复制到剪贴板的异常的更多信息

System.ArgumentNullException was unhandled
  HResult=-2147467261
  Message=Value cannot be null.
Parameter name: source
  Source=System.Core
  ParamName=source
  StackTrace:
       at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
       at HandBrake.Interop.HandBrakeInstance.GetTitle(Int32 titleNumber) in c:\HandBrake\Hudson\workspace\Release_WindowsGui64\0.9.9\win\CS\HandBrake.Interop\HandBrakeInterop\HandBrakeInstance.cs:line 1604
       at HandBrake.Interop.HandBrakeInstance.GetTitleIndex(Int32 titleNumber) in c:\HandBrake\Hudson\workspace\Release_WindowsGui64\0.9.9\win\CS\HandBrake.Interop\HandBrakeInterop\HandBrakeInstance.cs:line 1614
       at HandBrake.Interop.HandBrakeInstance.StartEncode(EncodeJob job, Boolean preview, Int32 previewNumber, Int32 previewSeconds, Double overallSelectedLengthSeconds) in c:\HandBrake\Hudson\workspace\Release_WindowsGui64\0.9.9\win\CS\HandBrake.Interop\HandBrakeInterop\HandBrakeInstance.cs:line 411
       at HandBrake.Interop.HandBrakeInstance.StartEncode(EncodeJob jobToStart) in c:\HandBrake\Hudson\workspace\Release_WindowsGui64\0.9.9\win\CS\HandBrake.Interop\HandBrakeInterop\HandBrakeInstance.cs:line 395
       at HandBrakeTest.Program.Main(String[] args) in c:\Users\user\Documents\Visual Studio 2012\Projects\HandBrakeTest\HandBrakeTest\Program.cs:line 53
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

编辑:

  1. 将手刹实例和编码作业的实例移到 main 之外并使其静态
  2. 在扫描完成事件中调用StartEncode

现在,异常是 Nullreferenceexception,详细信息如下:

System.NullReferenceException was unhandled by user code
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=HandBrakeInterop
  StackTrace:
       at HandBrake.Interop.InteropUtilities.ReadStructure[T](IntPtr structPtr) in c:\HandBrake\Hudson\workspace\Release_WindowsGui64\0.9.9\win\CS\HandBrake.Interop\HandBrakeInterop\InteropUtilities.cs:line 31
       at HandBrake.Interop.HandBrakeInstance.StartEncode(EncodeJob job, Boolean preview, Int32 previewNumber, Int32 previewSeconds, Double overallSelectedLengthSeconds) in c:\HandBrake\Hudson\workspace\Release_WindowsGui64\0.9.9\win\CS\HandBrake.Interop\HandBrakeInterop\HandBrakeInstance.cs:line 412
       at HandBrake.Interop.HandBrakeInstance.StartEncode(EncodeJob jobToStart) in c:\HandBrake\Hudson\workspace\Release_WindowsGui64\0.9.9\win\CS\HandBrake.Interop\HandBrakeInterop\HandBrakeInstance.cs:line 395
       at HandBrakeTest.Program.objHb_ScanCompleted(Object sender, EventArgs e) in c:\Users\user\Documents\Visual Studio 2012\Projects\HandBrakeTest\HandBrakeTest\Program.cs:line 65
       at HandBrake.Interop.HandBrakeInstance.PollScanProgress() in c:\HandBrake\Hudson\workspace\Release_WindowsGui64\0.9.9\win\CS\HandBrake.Interop\HandBrakeInterop\HandBrakeInstance.cs:line 811
       at HandBrake.Interop.HandBrakeInstance.<StartScan>b__2(Object o, ElapsedEventArgs e) in c:\HandBrake\Hudson\workspace\Release_WindowsGui64\0.9.9\win\CS\HandBrake.Interop\HandBrakeInterop\HandBrakeInstance.cs:line 752
       at System.Timers.Timer.MyTimerCallback(Object state)
  InnerException: 

提前致谢。

c# exception video-encoding handbrake
3个回答
7
投票

是的,HandBrakeInterop 并不是最简单的 API,只需为其编写一些代码即可;现在它更适合完整的编码器 GUI;它不能很好地回归默认值。从 XML 中获取 EncodingProfile 是一个非常好的主意。

这是一个与 HandBrakeInterop 交互的最小工作项目: http://engy.us/misc/HandBrakeInteropExample.zip

一些相关内容:

instance = new HandBrakeInstance();
instance.Initialize(verbosity: 1);
instance.ScanCompleted += instance_ScanCompleted;
instance.StartScan(SourceFile, previewCount: 10);
  • 1 是默认详细程度。您传入的“5”无效。
  • 您可能希望在 StartScan 上传递预览计数的实际值:它使用这些静态预览来执行自动裁剪检测和组合检测等操作。
var 作业 = 新的 EncodeJob
    {
        编码配置文件=配置文件,
        范围类型 = VideoRangeType.All,
        标题=1,
        源路径 = 源文件,
        OutputPath = AppDomain.CurrentDomain.BaseDirectory + "Output.mp4",
        ChosenAudioTracks = 新列表 { 1 },
        字幕=新字幕
            {
                SourceSubtitles = new List(),
                SrtSubtitles = 新列表()
            }
    };
  • 您需要传入要编码的标题(从 1 开始的索引)。对于文件来说,这很少相关;该功能专为 DVD/蓝光扫描而设计。
  • 您必须传入
    RangeType
    和范围的具体信息:例如,如果您选择
    RangeType
    中的
    Frames
    ,那么您需要指定
    FramesStart
    FramesEnd
    RangeType.All
    最简单,因为您不需要指定任何额外的内容。
  • 您需要指定所选音轨索引的列表(从 1 开始)。通常不适用于文件,但适用于具有多种语言的 DVD/蓝光光盘。
  • 现在你必须在字幕下给它一些东西,否则它会崩溃。这实际上是一个错误;有一些情况我没有正确防护。我将来会解决这个问题。
如果您想查看 API 的完整参考实现,请查看

VidCoder。 HandBrake 已经开始使用它了一些,但它还没有解决所有功能,如静态预览和暂停/恢复。

更新:所需的代码现在看起来完全不同,并且目标为 HandBrake.ApplicationServices.dll。新的最小项目:http://engy.us/misc/HBInteropExampleV3.zip

一个显着的区别是编码作业现在以 JSON 形式指定。这与 HandBrake/VidCoder 中的编码日志中吐出的 JSON blob 完全相同,因此您可以从那里窃取它并进行调整。


1
投票
我快速查看了源代码

这里。看起来 StartScan

 实际上是一个异步调用,您必须等待 
ScanCompleted
 事件引发才能调用 
StartEncode

似乎发生的情况是

Titles

 集合为空。这是用一个私有方法 
PollScanProgress
 填充的,它似乎会触发一个检查扫描进度的计时器。定时器设置在
StartScan


0
投票
我正在根据您的 HBInteropExampleV3.zip 代码开发一些代码,但按照建议从我的计算机上的实际作业日志中获取转换参数。我遇到的问题是,您的实用程序 JsonEncodeObject 和示例 JSON 使用所有编解码器规范的数字,而我的日志使用有意义的字符串,例如“x264”。您是否已经更新了可以接受字符串的代码,或者您能否向我指出一个查找列表,以便我可以选择正确的替换项? 谢谢,安德鲁

© www.soinside.com 2019 - 2024. All rights reserved.