Fixed: Format bitrate for primary streams in media info

Co-authored-by: Mark McDowall <markus.mcd5@gmail.com>
This commit is contained in:
Bogdan 2025-01-24 15:43:08 +02:00
parent 1edcbee5e1
commit 528b93dabe
3 changed files with 52 additions and 7 deletions

View file

@ -2,6 +2,7 @@ import React from 'react';
import DescriptionList from 'Components/DescriptionList/DescriptionList'; import DescriptionList from 'Components/DescriptionList/DescriptionList';
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem'; import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
import MediaInfoProps from 'typings/MediaInfo'; import MediaInfoProps from 'typings/MediaInfo';
import formatBitrate from 'Utilities/Number/formatBitrate';
import getEntries from 'Utilities/Object/getEntries'; import getEntries from 'Utilities/Object/getEntries';
function MediaInfo(props: MediaInfoProps) { function MediaInfo(props: MediaInfoProps) {
@ -16,9 +17,19 @@ function MediaInfo(props: MediaInfoProps) {
return null; return null;
} }
if (key === 'audioBitrate' || key === 'videoBitrate') {
return ( return (
<DescriptionListItem key={key} title={title} data={props[key]} /> <DescriptionListItem
key={key}
title={title}
data={
<span title={value.toString()}>{formatBitrate(value)}</span>
}
/>
); );
}
return <DescriptionListItem key={key} title={title} data={value} />;
})} })}
</DescriptionList> </DescriptionList>
); );

View file

@ -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;

View file

@ -21,8 +21,8 @@ public class VideoFileInfoReader : IVideoFileInfoReader
private readonly Logger _logger; private readonly Logger _logger;
private readonly List<FFProbePixelFormat> _pixelFormats; private readonly List<FFProbePixelFormat> _pixelFormats;
public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 8; public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 14;
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 13; public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 14;
private static readonly string[] ValidHdrColourPrimaries = { "bt2020" }; private static readonly string[] ValidHdrColourPrimaries = { "bt2020" };
private static readonly string[] HlgTransferFunctions = { "arib-std-b67" }; private static readonly string[] HlgTransferFunctions = { "arib-std-b67" };
@ -80,7 +80,7 @@ public MediaInfoModel GetMediaInfo(string filename)
mediaInfoModel.VideoFormat = primaryVideoStream?.CodecName; mediaInfoModel.VideoFormat = primaryVideoStream?.CodecName;
mediaInfoModel.VideoCodecID = primaryVideoStream?.CodecTagString; mediaInfoModel.VideoCodecID = primaryVideoStream?.CodecTagString;
mediaInfoModel.VideoProfile = primaryVideoStream?.Profile; mediaInfoModel.VideoProfile = primaryVideoStream?.Profile;
mediaInfoModel.VideoBitrate = primaryVideoStream?.BitRate ?? 0; mediaInfoModel.VideoBitrate = GetBitrate(primaryVideoStream);
mediaInfoModel.VideoMultiViewCount = primaryVideoStream?.Tags?.ContainsKey("stereo_mode") ?? false ? 2 : 1; mediaInfoModel.VideoMultiViewCount = primaryVideoStream?.Tags?.ContainsKey("stereo_mode") ?? false ? 2 : 1;
mediaInfoModel.VideoBitDepth = GetPixelFormat(primaryVideoStream?.PixelFormat)?.Components.Min(x => x.BitDepth) ?? 8; mediaInfoModel.VideoBitDepth = GetPixelFormat(primaryVideoStream?.PixelFormat)?.Components.Min(x => x.BitDepth) ?? 8;
mediaInfoModel.VideoColourPrimaries = primaryVideoStream?.ColorPrimaries; mediaInfoModel.VideoColourPrimaries = primaryVideoStream?.ColorPrimaries;
@ -91,7 +91,7 @@ public MediaInfoModel GetMediaInfo(string filename)
mediaInfoModel.AudioFormat = analysis.PrimaryAudioStream?.CodecName; mediaInfoModel.AudioFormat = analysis.PrimaryAudioStream?.CodecName;
mediaInfoModel.AudioCodecID = analysis.PrimaryAudioStream?.CodecTagString; mediaInfoModel.AudioCodecID = analysis.PrimaryAudioStream?.CodecTagString;
mediaInfoModel.AudioProfile = analysis.PrimaryAudioStream?.Profile; 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.RunTime = GetBestRuntime(analysis.PrimaryAudioStream?.Duration, primaryVideoStream?.Duration, analysis.Format.Duration);
mediaInfoModel.AudioStreamCount = analysis.AudioStreams.Count; mediaInfoModel.AudioStreamCount = analysis.AudioStreams.Count;
mediaInfoModel.AudioChannels = analysis.PrimaryAudioStream?.Channels ?? 0; mediaInfoModel.AudioChannels = analysis.PrimaryAudioStream?.Channels ?? 0;
@ -161,6 +161,21 @@ private static TimeSpan GetBestRuntime(TimeSpan? audio, TimeSpan? video, TimeSpa
return video.Value; 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) private VideoStream GetPrimaryVideoStream(IMediaAnalysis mediaAnalysis)
{ {
if (mediaAnalysis.VideoStreams.Count <= 1) if (mediaAnalysis.VideoStreams.Count <= 1)