让手刹编码器工作

时间:2013-05-26 18:45:52

标签: c# exception video-encoding handbrake

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

Handbrake Encoder error

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

  1. 在我的电脑上安装了手刹
  2. 添加了对HandBrakeInterop.dll
  3. 的引用
  4. 将所有其他必需的dll复制到我的调试文件夹,甚至尝试将它们添加为参考
  5. 尝试从x86 / x64更改调试版本
  6. 我在哪里不在正确的轨道上?

    这是我的代码:

          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
    3. 现在,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: 
      

      提前致谢。

2 个答案:

答案 0 :(得分:6)

是的,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 = new EncodeJob
    {
        EncodingProfile = profile,
        RangeType = VideoRangeType.All,
        Title = 1,
        SourcePath = SourceFile,
        OutputPath = AppDomain.CurrentDomain.BaseDirectory + "Output.mp4",
        ChosenAudioTracks = new List { 1 },
        Subtitles = new Subtitles
            {
                SourceSubtitles = new List(),
                SrtSubtitles = new List()
            }
    };
  • 您需要传入要编码的标题(基于1的索引)。对于文件,这很少相关;该功能专为DVD /蓝光扫描而设计。
  • 您必须同时传递RangeType和范围的详细信息:例如,如果您选择RangeType Frames,则需要指定FramesStartFramesEndRangeType.All最简单,因为您不需要另外指定任何内容。
  • 您需要指定所选音轨索引的列表(从1开始)。通常不适用于文件,但适用于具有多种语言的DVD /蓝光光盘。
  • 现在你必须在Subtitles下给它一些东西,否则它会崩溃。这实际上是一个bug;有几个案例我没有正确守护。我将来会解决这个问题。

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

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

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

答案 1 :(得分:1)

我快速浏览了源代码here。看来StartScan实际上是异步调用,您必须等待ScanCompleted事件被提升才能调用StartEncode

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