diff --git a/frontend/src/MovieFile/Editor/MediaInfo.tsx b/frontend/src/MovieFile/Editor/MediaInfo.tsx
index d0a8951750..f5e3db21f6 100644
--- a/frontend/src/MovieFile/Editor/MediaInfo.tsx
+++ b/frontend/src/MovieFile/Editor/MediaInfo.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import DescriptionList from 'Components/DescriptionList/DescriptionList';
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
import MediaInfoProps from 'typings/MediaInfo';
+import formatBitrate from 'Utilities/Number/formatBitrate';
import getEntries from 'Utilities/Object/getEntries';
function MediaInfo(props: MediaInfoProps) {
@@ -16,9 +17,19 @@ function MediaInfo(props: MediaInfoProps) {
return null;
}
- return (
-
- );
+ if (key === 'audioBitrate' || key === 'videoBitrate') {
+ return (
+ {formatBitrate(value)}
+ }
+ />
+ );
+ }
+
+ return ;
})}
);
diff --git a/frontend/src/Utilities/Number/formatBitrate.ts b/frontend/src/Utilities/Number/formatBitrate.ts
new file mode 100644
index 0000000000..5d7d25ae4a
--- /dev/null
+++ b/frontend/src/Utilities/Number/formatBitrate.ts
@@ -0,0 +1,19 @@
+import { filesize } from 'filesize';
+
+function formatBitrate(input: string | number) {
+ const size = Number(input);
+
+ if (isNaN(size)) {
+ return '';
+ }
+
+ const { value, symbol } = filesize(size, {
+ base: 10,
+ round: 1,
+ output: 'object',
+ });
+
+ return `${value} ${symbol}/s`;
+}
+
+export default formatBitrate;
diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs
index 868d7749a6..cbfb17e888 100644
--- a/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs
+++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs
@@ -21,8 +21,8 @@ public class VideoFileInfoReader : IVideoFileInfoReader
private readonly Logger _logger;
private readonly List _pixelFormats;
- public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 8;
- public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 13;
+ public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 14;
+ public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 14;
private static readonly string[] ValidHdrColourPrimaries = { "bt2020" };
private static readonly string[] HlgTransferFunctions = { "arib-std-b67" };
@@ -80,7 +80,7 @@ public MediaInfoModel GetMediaInfo(string filename)
mediaInfoModel.VideoFormat = primaryVideoStream?.CodecName;
mediaInfoModel.VideoCodecID = primaryVideoStream?.CodecTagString;
mediaInfoModel.VideoProfile = primaryVideoStream?.Profile;
- mediaInfoModel.VideoBitrate = primaryVideoStream?.BitRate ?? 0;
+ mediaInfoModel.VideoBitrate = GetBitrate(primaryVideoStream);
mediaInfoModel.VideoMultiViewCount = primaryVideoStream?.Tags?.ContainsKey("stereo_mode") ?? false ? 2 : 1;
mediaInfoModel.VideoBitDepth = GetPixelFormat(primaryVideoStream?.PixelFormat)?.Components.Min(x => x.BitDepth) ?? 8;
mediaInfoModel.VideoColourPrimaries = primaryVideoStream?.ColorPrimaries;
@@ -91,7 +91,7 @@ public MediaInfoModel GetMediaInfo(string filename)
mediaInfoModel.AudioFormat = analysis.PrimaryAudioStream?.CodecName;
mediaInfoModel.AudioCodecID = analysis.PrimaryAudioStream?.CodecTagString;
mediaInfoModel.AudioProfile = analysis.PrimaryAudioStream?.Profile;
- mediaInfoModel.AudioBitrate = analysis.PrimaryAudioStream?.BitRate ?? 0;
+ mediaInfoModel.AudioBitrate = GetBitrate(analysis.PrimaryAudioStream);
mediaInfoModel.RunTime = GetBestRuntime(analysis.PrimaryAudioStream?.Duration, primaryVideoStream?.Duration, analysis.Format.Duration);
mediaInfoModel.AudioStreamCount = analysis.AudioStreams.Count;
mediaInfoModel.AudioChannels = analysis.PrimaryAudioStream?.Channels ?? 0;
@@ -161,6 +161,21 @@ private static TimeSpan GetBestRuntime(TimeSpan? audio, TimeSpan? video, TimeSpa
return video.Value;
}
+ private static long GetBitrate(MediaStream mediaStream)
+ {
+ if (mediaStream?.BitRate is > 0)
+ {
+ return mediaStream.BitRate;
+ }
+
+ if ((mediaStream?.Tags?.TryGetValue("BPS", out var bitratePerSecond) ?? false) && bitratePerSecond.IsNotNullOrWhiteSpace())
+ {
+ return Convert.ToInt64(bitratePerSecond);
+ }
+
+ return 0;
+ }
+
private VideoStream GetPrimaryVideoStream(IMediaAnalysis mediaAnalysis)
{
if (mediaAnalysis.VideoStreams.Count <= 1)