diff --git a/frontend/src/Episode/Summary/MediaInfo.tsx b/frontend/src/Episode/Summary/MediaInfo.tsx index d0a895175..f5e3db21f 100644 --- a/frontend/src/Episode/Summary/MediaInfo.tsx +++ b/frontend/src/Episode/Summary/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 000000000..5d7d25ae4 --- /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 4aa850af3..8279aefc5 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs @@ -21,8 +21,8 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo 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 = 11; + public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 12; + public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 12; private static readonly string[] ValidHdrColourPrimaries = { "bt2020" }; private static readonly string[] HlgTransferFunctions = { "arib-std-b67" }; @@ -81,7 +81,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo mediaInfoModel.VideoFormat = primaryVideoStream?.CodecName; mediaInfoModel.VideoCodecID = primaryVideoStream?.CodecTagString; mediaInfoModel.VideoProfile = primaryVideoStream?.Profile; - mediaInfoModel.VideoBitrate = primaryVideoStream?.BitRate ?? 0; + mediaInfoModel.VideoBitrate = GetBitrate(primaryVideoStream); mediaInfoModel.VideoBitDepth = GetPixelFormat(primaryVideoStream?.PixelFormat)?.Components.Min(x => x.BitDepth) ?? 8; mediaInfoModel.VideoColourPrimaries = primaryVideoStream?.ColorPrimaries; mediaInfoModel.VideoTransferCharacteristics = primaryVideoStream?.ColorTransfer; @@ -91,7 +91,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo 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 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo 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)