5

我无法让Handbrake在 C# 中为我工作。它不断抛出错误“值不能为空”。. 正如您在下面的屏幕截图中看到的那样,我根据我所知道的尝试了几件事。我将不胜感激您的任何指导,以帮助我完成这项工作。

手刹编码器错误

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

  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. 将 handbrakeinstance 和 encodingjob 的实例移到 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: 

提前致谢。

4

2 回答 2

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 上为 previewCount 传递一个实际值:它使用这些静态预览来执行自动裁剪检测和梳理检测等操作。
var job = 新的 EncodeJob
    {
        编码配置文件 = 配置文件,
        RangeType = VideoRangeType.All,
        标题 = 1,
        源路径 = 源文件,
        OutputPath = AppDomain.CurrentDomain.BaseDirectory + "Output.mp4",
        ChosenAudioTracks = 新列表 { 1 },
        字幕 = 新字幕
            {
                SourceSubtitles = 新列表(),
                SrtSubtitles = 新列表()
            }
    };
  • 您需要传入要编码的标题(基于 1 的索引)。对于文件,这很少相关;该功能专为 DVD/蓝光扫描而设计。
  • 您必须同时传递 aRangeType和范围的细节:例如,如果您选择 a RangeTypeFrames那么您需要指定FramesStartand FramesEndRangeType.All是最简单的,因为您不需要指定任何额外的内容。
  • 您需要指定所选音轨索引的列表(从 1 开始)。通常对文件没有用,但对有多种语言的 DVD/蓝光光盘有用。
  • 现在你必须在字幕下给它一些东西,否则它会崩溃。这实际上是一个错误;有一些情况我没有正确保护。我将来会解决这个问题。

如果您想查看 API 的完整参考实现,请查看VidCoder 。HandBrake 已经开始使用它,但它还没有使用静态预览和暂停/恢复等所有功能。

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

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

于 2013-05-27T17:48:15.763 回答
1

我在这里快速浏览了源代码。看起来这StartScan实际上是一个异步调用,您必须在调用之前等待ScanCompleted引发事件StartEncode

似乎正在发生的是该Titles集合为空。这是在一个私有方法中填充的,该方法PollScanProgress似乎在检查扫描进度的计时器上触发。计时器设置在StartScan.

于 2013-05-27T06:08:49.160 回答