使用C#调用FFProbe获取视频码率返回Null引发空引用异常求排查
问题
我尝试在C#中使用FFProbe获取视频文件的码率数据,但在将返回字符串解析为整数前,该字符串意外为Null,导致int.Parse抛出NullReferenceException异常。以下是我编写的获取码率的函数:
private float GetBitrate() { string command = $"ffprobe -v quiet -select_streams v:0 -show_entries format=bit_rate -of default=noprint_wrappers=1 \"{sourceField.text}\""; string result = null; using (var p = new Process()) { p.StartInfo.FileName = ffprobePath; p.StartInfo.Arguments = command; p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.RedirectStandardOutput = true; p.OutputDataReceived += (s, e) => result = e.Data; p.ErrorDataReceived += (s, e) => throw new ArgumentException(e.Data); p.Start(); p.BeginOutputReadLine(); p.BeginErrorReadLine(); p.WaitForExit(); } int value = int.Parse(result.Replace("bit_rate=", string.Empty).Trim()); return (float)value / 1000; }
我在cmd中测试该命令可以正常运行,但代码中却无法正常工作,请问我的代码存在什么问题?
分析与解决
你的代码存在三个核心问题:
- 输出被覆盖为Null:
OutputDataReceived事件会多次触发,最后一次触发时e.Data为null(表示输出结束),你直接用result = e.Data会把之前获取到的有效输出覆盖成null,导致后续解析失败。 - 错误处理过于激进:
ErrorDataReceived事件中直接抛出异常会中断进程执行,而且ffprobe可能会将非错误信息输出到stderr,直接抛出异常会误判正常情况。 - 解析前未做空值校验:没有判断
result是否为null就直接调用Replace和Trim,必然触发空引用异常。
修正后的代码如下:
private float GetBitrate() { var outputBuilder = new StringBuilder(); var errorBuilder = new StringBuilder(); using (var p = new Process()) { p.StartInfo.FileName = ffprobePath; p.StartInfo.Arguments = $"-v quiet -select_streams v:0 -show_entries format=bit_rate -of default=noprint_wrappers=1 \"{sourceField.text}\""; p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.RedirectStandardOutput = true; // 累加输出内容,跳过空的结束信号 p.OutputDataReceived += (s, e) => { if (!string.IsNullOrEmpty(e.Data)) outputBuilder.Append(e.Data); }; // 收集错误输出,不直接抛出异常 p.ErrorDataReceived += (s, e) => { if (!string.IsNullOrEmpty(e.Data)) errorBuilder.Append(e.Data); }; p.Start(); p.BeginOutputReadLine(); p.BeginErrorReadLine(); p.WaitForExit(); } // 处理错误输出 string errorMsg = errorBuilder.ToString().Trim(); if (!string.IsNullOrEmpty(errorMsg)) { throw new InvalidOperationException($"FFProbe执行出错: {errorMsg}"); } string result = outputBuilder.ToString().Trim(); if (string.IsNullOrEmpty(result)) { throw new InvalidOperationException("未获取到有效码率数据"); } // 解析码率,用TryParse避免格式异常 string bitrateStr = result.Replace("bit_rate=", string.Empty).Trim(); if (!int.TryParse(bitrateStr, out int bitrateValue)) { throw new FormatException($"无法解析码率值: {bitrateStr}"); } return (float)bitrateValue / 1000; }
内容的提问来源于stack exchange,提问作者Sunny Leung
相关产品推荐
相关产品推荐

