2021-05-20 22:10:19 +02:00
#nullable disable
2020-08-04 16:20:52 +02:00
2019-01-13 21:02:23 +01:00
using System ;
2018-12-14 10:40:55 +01:00
using System.Collections.Generic ;
using System.Globalization ;
using System.IO ;
using System.Linq ;
using System.Text ;
2021-07-27 17:09:23 +02:00
using System.Text.RegularExpressions ;
2018-12-14 10:40:55 +01:00
using System.Xml ;
2023-03-25 18:52:02 +01:00
using Jellyfin.Data.Enums ;
2021-07-09 02:06:38 +02:00
using Jellyfin.Extensions ;
2018-12-14 10:40:55 +01:00
using MediaBrowser.Controller.Library ;
2018-12-31 00:28:23 +01:00
using MediaBrowser.Model.Dto ;
using MediaBrowser.Model.Entities ;
2019-03-14 22:31:51 +01:00
using MediaBrowser.Model.Globalization ;
2018-12-14 10:40:55 +01:00
using MediaBrowser.Model.MediaInfo ;
2018-12-31 00:28:23 +01:00
using Microsoft.Extensions.Logging ;
2018-12-14 10:40:55 +01:00
namespace MediaBrowser.MediaEncoding.Probing
{
2023-07-28 07:16:45 +02:00
/// <summary>
/// Class responsible for normalizing FFprobe output.
/// </summary>
2018-12-14 10:40:55 +01:00
public class ProbeResultNormalizer
{
2020-08-04 17:08:09 +02:00
// When extracting subtitles, the maximum length to consider (to avoid invalid filenames)
private const int MaxSubtitleDescriptionExtractionLength = 100 ;
private const string ArtistReplaceValue = " | " ;
private readonly char [ ] _nameDelimiters = { '/' , '|' , ';' , '\\' } ;
2021-12-24 18:28:27 +01:00
private static readonly Regex _performerPattern = new ( @"(?<name>.*) \((?<instrument>.*)\)" ) ;
2021-08-02 03:48:45 +02:00
2018-12-14 10:40:55 +01:00
private readonly ILogger _logger ;
2019-03-14 22:31:51 +01:00
private readonly ILocalizationManager _localization ;
2018-12-14 10:40:55 +01:00
2021-05-05 14:39:50 +02:00
private string [ ] _splitWhiteList ;
2020-08-04 17:08:09 +02:00
2023-07-28 07:16:45 +02:00
/// <summary>
/// Initializes a new instance of the <see cref="ProbeResultNormalizer"/> class.
/// </summary>
/// <param name="logger">The <see cref="ILogger{ProbeResultNormalizer}"/> for use with the <see cref="ProbeResultNormalizer"/> instance.</param>
/// <param name="localization">The <see cref="ILocalizationManager"/> for use with the <see cref="ProbeResultNormalizer"/> instance.</param>
2020-02-23 10:53:51 +01:00
public ProbeResultNormalizer ( ILogger logger , ILocalizationManager localization )
2018-12-14 10:40:55 +01:00
{
_logger = logger ;
2019-03-14 22:31:51 +01:00
_localization = localization ;
2018-12-14 10:40:55 +01:00
}
2021-07-10 17:04:00 +02:00
private IReadOnlyList < string > SplitWhitelist = > _splitWhiteList ? ? = new string [ ]
{
"AC/DC" ,
2022-09-10 22:30:53 +02:00
"A/T/O/S" ,
2022-01-27 21:52:57 +01:00
"As/Hi Soundworks" ,
2021-07-10 17:04:00 +02:00
"Au/Ra" ,
2021-12-12 01:26:47 +01:00
"Bremer/McCoy" ,
2022-09-11 19:27:58 +02:00
"b/bqスタヂオ" ,
"DOV/S" ,
"DJ'TEKINA//SOMETHING" ,
"IX/ON" ,
"J-CORE SLi//CER" ,
"M(a/u)SH" ,
"Kaoru/Brilliance" ,
"signum/ii" ,
"Richiter(LORB/DUGEM DI BARAT)" ,
2021-07-10 17:04:00 +02:00
"이달의 소녀 1/3" ,
2022-01-27 21:52:57 +01:00
"R!N / Gemie" ,
2021-07-10 17:04:00 +02:00
"LOONA 1/3" ,
"LOONA / yyxy" ,
"LOONA / ODD EYE CIRCLE" ,
2021-10-06 10:32:28 +02:00
"K/DA" ,
2022-09-11 19:27:58 +02:00
"22/7" ,
"諭吉佳作/men" ,
2023-01-26 00:28:17 +01:00
"//dARTH nULL" ,
"Phantom/Ghost" ,
2023-04-20 15:39:34 +02:00
"She/Her/Hers" ,
2023-04-29 13:47:09 +02:00
"5/8erl in Ehr'n" ,
2023-05-04 21:04:38 +02:00
"Smith/Kotzen" ,
2023-10-03 05:00:51 +02:00
"We;Na" ,
2021-07-10 17:04:00 +02:00
} ;
2021-05-05 14:39:50 +02:00
2023-07-28 07:16:45 +02:00
/// <summary>
/// Transforms a FFprobe response into its <see cref="MediaInfo"/> equivalent.
/// </summary>
/// <param name="data">The <see cref="InternalMediaInfoResult"/>.</param>
/// <param name="videoType">The <see cref="VideoType"/>.</param>
/// <param name="isAudio">A boolean indicating whether the media is audio.</param>
/// <param name="path">Path to media file.</param>
/// <param name="protocol">Path media protocol.</param>
/// <returns>The <see cref="MediaInfo"/>.</returns>
2018-12-14 10:40:55 +01:00
public MediaInfo GetMediaInfo ( InternalMediaInfoResult data , VideoType ? videoType , bool isAudio , string path , MediaProtocol protocol )
{
var info = new MediaInfo
{
Path = path ,
2020-08-20 12:16:24 +02:00
Protocol = protocol ,
VideoType = videoType
2018-12-14 10:40:55 +01:00
} ;
FFProbeHelpers . NormalizeFFProbeResult ( data ) ;
SetSize ( data , info ) ;
2020-02-23 10:53:51 +01:00
var internalStreams = data . Streams ? ? Array . Empty < MediaStreamInfo > ( ) ;
2018-12-14 10:40:55 +01:00
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
info . MediaStreams = internalStreams . Select ( s = > GetMediaStream ( isAudio , s , data . Format ) )
2022-12-05 15:01:13 +01:00
. Where ( i = > i is not null )
2018-12-14 10:40:55 +01:00
// Drop subtitle streams if we don't know the codec because it will just cause failures if we don't know how to handle them
. Where ( i = > i . Type ! = MediaStreamType . Subtitle | | ! string . IsNullOrWhiteSpace ( i . Codec ) )
. ToList ( ) ;
2021-04-17 12:19:09 +02:00
info . MediaAttachments = internalStreams . Select ( GetMediaAttachment )
2022-12-05 15:01:13 +01:00
. Where ( i = > i is not null )
2019-10-03 17:51:28 +02:00
. ToList ( ) ;
2022-12-05 15:01:13 +01:00
if ( data . Format is not null )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
info . Container = NormalizeFormat ( data . Format . FormatName ) ;
2018-12-14 10:40:55 +01:00
2023-02-19 16:52:29 +01:00
if ( int . TryParse ( data . Format . BitRate , CultureInfo . InvariantCulture , out var value ) )
2018-12-14 10:40:55 +01:00
{
2023-02-19 16:52:29 +01:00
info . Bitrate = value ;
2018-12-14 10:40:55 +01:00
}
}
var tags = new Dictionary < string , string > ( StringComparer . OrdinalIgnoreCase ) ;
2023-02-01 14:58:04 +01:00
var tagStreamType = isAudio ? CodecType . Audio : CodecType . Video ;
2018-12-14 10:40:55 +01:00
2023-02-01 14:58:04 +01:00
var tagStream = data . Streams ? . FirstOrDefault ( i = > i . CodecType = = tagStreamType ) ;
2018-12-14 10:40:55 +01:00
2022-12-05 15:01:13 +01:00
if ( tagStream ? . Tags is not null )
2021-07-09 02:06:38 +02:00
{
foreach ( var ( key , value ) in tagStream . Tags )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
tags [ key ] = value ;
2018-12-14 10:40:55 +01:00
}
}
2022-12-05 15:01:13 +01:00
if ( data . Format ? . Tags is not null )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
foreach ( var ( key , value ) in data . Format . Tags )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
tags [ key ] = value ;
2018-12-14 10:40:55 +01:00
}
}
FetchGenres ( info , tags ) ;
2021-07-09 02:06:38 +02:00
info . Name = tags . GetFirstNotNullNorWhiteSpaceValue ( "title" , "title-eng" ) ;
info . ForcedSortName = tags . GetFirstNotNullNorWhiteSpaceValue ( "sort_name" , "title-sort" , "titlesort" ) ;
info . Overview = tags . GetFirstNotNullNorWhiteSpaceValue ( "synopsis" , "description" , "desc" ) ;
2018-12-14 10:40:55 +01:00
2020-02-17 14:56:31 +01:00
info . IndexNumber = FFProbeHelpers . GetDictionaryNumericValue ( tags , "episode_sort" ) ;
info . ParentIndexNumber = FFProbeHelpers . GetDictionaryNumericValue ( tags , "season_number" ) ;
2021-07-09 02:06:38 +02:00
info . ShowName = tags . GetValueOrDefault ( "show_name" ) ;
2018-12-14 10:40:55 +01:00
info . ProductionYear = FFProbeHelpers . GetDictionaryNumericValue ( tags , "date" ) ;
2021-04-04 23:34:29 +02:00
// Several different forms of retail/premiere date
info . PremiereDate =
2021-07-05 03:27:03 +02:00
FFProbeHelpers . GetDictionaryDateTime ( tags , "originaldate" ) ? ?
2021-04-04 23:34:29 +02:00
FFProbeHelpers . GetDictionaryDateTime ( tags , "retaildate" ) ? ?
2018-12-14 10:40:55 +01:00
FFProbeHelpers . GetDictionaryDateTime ( tags , "retail date" ) ? ?
FFProbeHelpers . GetDictionaryDateTime ( tags , "retail_date" ) ? ?
2021-04-04 15:08:08 +02:00
FFProbeHelpers . GetDictionaryDateTime ( tags , "date_released" ) ? ?
2022-12-19 19:52:09 +01:00
FFProbeHelpers . GetDictionaryDateTime ( tags , "date" ) ? ?
FFProbeHelpers . GetDictionaryDateTime ( tags , "creation_time" ) ;
2018-12-14 10:40:55 +01:00
2021-04-04 23:34:29 +02:00
// Set common metadata for music (audio) and music videos (video)
2021-07-09 02:06:38 +02:00
info . Album = tags . GetValueOrDefault ( "album" ) ;
2021-04-04 23:34:29 +02:00
2021-07-09 02:06:38 +02:00
if ( tags . TryGetValue ( "artists" , out var artists ) & & ! string . IsNullOrWhiteSpace ( artists ) )
2021-04-04 23:34:29 +02:00
{
2021-07-09 02:06:38 +02:00
info . Artists = SplitDistinctArtists ( artists , new [ ] { '/' , ';' } , false ) . ToArray ( ) ;
2021-04-04 23:34:29 +02:00
}
else
{
2021-07-09 02:06:38 +02:00
var artist = tags . GetFirstNotNullNorWhiteSpaceValue ( "artist" ) ;
2022-12-05 15:00:20 +01:00
info . Artists = artist is null
2021-07-09 02:06:38 +02:00
? Array . Empty < string > ( )
: SplitDistinctArtists ( artist , _nameDelimiters , true ) . ToArray ( ) ;
2021-04-04 23:34:29 +02:00
}
2021-07-09 02:06:38 +02:00
// Guess ProductionYear from PremiereDate if missing
2021-04-04 23:34:29 +02:00
if ( ! info . ProductionYear . HasValue & & info . PremiereDate . HasValue )
{
info . ProductionYear = info . PremiereDate . Value . Year ;
}
// Set mediaType-specific metadata
2018-12-14 10:40:55 +01:00
if ( isAudio )
{
SetAudioRuntimeTicks ( data , info ) ;
// tags are normally located under data.format, but we've seen some cases with ogg where they're part of the info stream
// so let's create a combined list of both
SetAudioInfoFromTags ( info , tags ) ;
}
else
{
FetchStudios ( info , tags , "copyright" ) ;
2021-07-09 02:06:38 +02:00
var iTunExtc = tags . GetFirstNotNullNorWhiteSpaceValue ( "iTunEXTC" ) ;
2022-12-05 15:01:13 +01:00
if ( iTunExtc is not null )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
var parts = iTunExtc . Split ( '|' , StringSplitOptions . RemoveEmptyEntries ) ;
2019-01-08 00:27:46 +01:00
// Example
2018-12-14 10:40:55 +01:00
// mpaa|G|100|For crude humor
if ( parts . Length > 1 )
{
info . OfficialRating = parts [ 1 ] ;
if ( parts . Length > 3 )
{
info . OfficialRatingDescription = parts [ 3 ] ;
}
}
}
2021-07-09 02:06:38 +02:00
var iTunXml = tags . GetFirstNotNullNorWhiteSpaceValue ( "iTunMOVI" ) ;
2022-12-05 15:01:13 +01:00
if ( iTunXml is not null )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
FetchFromItunesInfo ( iTunXml , info ) ;
2018-12-14 10:40:55 +01:00
}
2022-12-05 15:01:13 +01:00
if ( data . Format is not null & & ! string . IsNullOrEmpty ( data . Format . Duration ) )
2018-12-14 10:40:55 +01:00
{
2021-09-26 16:14:36 +02:00
info . RunTimeTicks = TimeSpan . FromSeconds ( double . Parse ( data . Format . Duration , CultureInfo . InvariantCulture ) ) . Ticks ;
2018-12-14 10:40:55 +01:00
}
FetchWtvInfo ( info , data ) ;
2022-12-05 15:01:13 +01:00
if ( data . Chapters is not null )
2018-12-14 10:40:55 +01:00
{
info . Chapters = data . Chapters . Select ( GetChapterInfo ) . ToArray ( ) ;
}
ExtractTimestamp ( info ) ;
2021-07-09 02:06:38 +02:00
if ( tags . TryGetValue ( "stereo_mode" , out var stereoMode ) & & string . Equals ( stereoMode , "left_right" , StringComparison . OrdinalIgnoreCase ) )
2018-12-14 10:40:55 +01:00
{
info . Video3DFormat = Video3DFormat . FullSideBySide ;
}
foreach ( var mediaStream in info . MediaStreams )
{
if ( mediaStream . Type = = MediaStreamType . Audio & & ! mediaStream . BitRate . HasValue )
{
mediaStream . BitRate = GetEstimatedAudioBitrate ( mediaStream . Codec , mediaStream . Channels ) ;
}
}
var videoStreamsBitrate = info . MediaStreams . Where ( i = > i . Type = = MediaStreamType . Video ) . Select ( i = > i . BitRate ? ? 0 ) . Sum ( ) ;
// If ffprobe reported the container bitrate as being the same as the video stream bitrate, then it's wrong
if ( videoStreamsBitrate = = ( info . Bitrate ? ? 0 ) )
{
info . InferTotalBitrate ( true ) ;
}
}
return info ;
}
private string NormalizeFormat ( string format )
{
if ( string . IsNullOrWhiteSpace ( format ) )
{
return null ;
}
2023-07-28 07:16:45 +02:00
// Input can be a list of multiple, comma-delimited formats - each of them needs to be checked
var splitFormat = format . Split ( ',' ) ;
for ( var i = 0 ; i < splitFormat . Length ; i + + )
2018-12-14 10:40:55 +01:00
{
2023-07-28 07:16:45 +02:00
// Handle MPEG-1 container
if ( string . Equals ( splitFormat [ i ] , "mpegvideo" , StringComparison . OrdinalIgnoreCase ) )
{
splitFormat [ i ] = "mpeg" ;
}
2018-12-14 10:40:55 +01:00
2023-07-28 07:16:45 +02:00
// Handle MPEG-2 container
else if ( string . Equals ( splitFormat [ i ] , "mpeg" , StringComparison . OrdinalIgnoreCase ) )
{
splitFormat [ i ] = "ts" ;
}
2023-02-17 00:26:03 +01:00
2023-07-28 07:16:45 +02:00
// Handle matroska container
else if ( string . Equals ( splitFormat [ i ] , "matroska" , StringComparison . OrdinalIgnoreCase ) )
{
splitFormat [ i ] = "mkv" ;
}
2023-02-17 00:26:03 +01:00
}
2018-12-14 10:40:55 +01:00
2023-07-28 07:16:45 +02:00
return string . Join ( ',' , splitFormat ) ;
2018-12-14 10:40:55 +01:00
}
private int? GetEstimatedAudioBitrate ( string codec , int? channels )
{
if ( ! channels . HasValue )
{
return null ;
}
var channelsValue = channels . Value ;
2020-11-11 10:08:50 +01:00
if ( string . Equals ( codec , "aac" , StringComparison . OrdinalIgnoreCase )
| | string . Equals ( codec , "mp3" , StringComparison . OrdinalIgnoreCase ) )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
switch ( channelsValue )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
case < = 2 :
return 192000 ;
case > = 5 :
return 320000 ;
2018-12-14 10:40:55 +01:00
}
}
2020-11-11 10:08:50 +01:00
if ( string . Equals ( codec , "ac3" , StringComparison . OrdinalIgnoreCase )
| | string . Equals ( codec , "eac3" , StringComparison . OrdinalIgnoreCase ) )
{
2021-07-09 02:06:38 +02:00
switch ( channelsValue )
2020-11-11 10:08:50 +01:00
{
2021-07-09 02:06:38 +02:00
case < = 2 :
return 192000 ;
case > = 5 :
return 640000 ;
2020-11-11 10:08:50 +01:00
}
}
if ( string . Equals ( codec , "flac" , StringComparison . OrdinalIgnoreCase )
| | string . Equals ( codec , "alac" , StringComparison . OrdinalIgnoreCase ) )
{
2021-07-09 02:06:38 +02:00
switch ( channelsValue )
2020-11-11 10:08:50 +01:00
{
2021-07-09 02:06:38 +02:00
case < = 2 :
return 960000 ;
case > = 5 :
return 2880000 ;
2020-11-11 10:08:50 +01:00
}
}
2018-12-14 10:40:55 +01:00
return null ;
}
private void FetchFromItunesInfo ( string xml , MediaInfo info )
{
// Make things simpler and strip out the dtd
var plistIndex = xml . IndexOf ( "<plist" , StringComparison . OrdinalIgnoreCase ) ;
if ( plistIndex ! = - 1 )
{
xml = xml . Substring ( plistIndex ) ;
}
xml = "<?xml version=\"1.0\"?>" + xml ;
// <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>cast</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>name</key>\n\t\t\t<string>Blender Foundation</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>name</key>\n\t\t\t<string>Janus Bager Kristensen</string>\n\t\t</dict>\n\t</array>\n\t<key>directors</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>name</key>\n\t\t\t<string>Sacha Goedegebure</string>\n\t\t</dict>\n\t</array>\n\t<key>studio</key>\n\t<string>Blender Foundation</string>\n</dict>\n</plist>\n
using ( var stream = new MemoryStream ( Encoding . UTF8 . GetBytes ( xml ) ) )
2019-02-02 16:12:16 +01:00
using ( var streamReader = new StreamReader ( stream ) )
2018-12-14 10:40:55 +01:00
{
2019-02-02 16:12:16 +01:00
try
2018-12-14 10:40:55 +01:00
{
2019-02-02 16:12:16 +01:00
using ( var reader = XmlReader . Create ( streamReader ) )
2018-12-14 10:40:55 +01:00
{
2019-02-02 16:12:16 +01:00
reader . MoveToContent ( ) ;
reader . Read ( ) ;
2018-12-14 10:40:55 +01:00
2019-02-02 16:12:16 +01:00
// Loop through each element
while ( ! reader . EOF & & reader . ReadState = = ReadState . Interactive )
{
if ( reader . NodeType = = XmlNodeType . Element )
2018-12-14 10:40:55 +01:00
{
2019-02-02 16:12:16 +01:00
switch ( reader . Name )
2018-12-14 10:40:55 +01:00
{
2019-02-02 16:12:16 +01:00
case "dict" :
if ( reader . IsEmptyElement )
{
reader . Read ( ) ;
continue ;
}
2020-06-15 23:43:52 +02:00
2019-02-02 16:12:16 +01:00
using ( var subtree = reader . ReadSubtree ( ) )
{
ReadFromDictNode ( subtree , info ) ;
}
2020-06-15 23:43:52 +02:00
2019-02-02 16:12:16 +01:00
break ;
default :
reader . Skip ( ) ;
break ;
2018-12-14 10:40:55 +01:00
}
}
2019-02-02 16:12:16 +01:00
else
{
reader . Read ( ) ;
}
2018-12-14 10:40:55 +01:00
}
}
2019-02-02 16:12:16 +01:00
}
catch ( XmlException )
{
// I've seen probe examples where the iTunMOVI value is just "<"
// So we should not allow this to fail the entire probing operation
2018-12-14 10:40:55 +01:00
}
}
}
private void ReadFromDictNode ( XmlReader reader , MediaInfo info )
{
string currentKey = null ;
2019-01-13 21:37:13 +01:00
var pairs = new List < NameValuePair > ( ) ;
2018-12-14 10:40:55 +01:00
reader . MoveToContent ( ) ;
reader . Read ( ) ;
// Loop through each element
while ( ! reader . EOF & & reader . ReadState = = ReadState . Interactive )
{
if ( reader . NodeType = = XmlNodeType . Element )
{
switch ( reader . Name )
{
case "key" :
if ( ! string . IsNullOrWhiteSpace ( currentKey ) )
{
ProcessPairs ( currentKey , pairs , info ) ;
}
2020-06-15 23:43:52 +02:00
2018-12-14 10:40:55 +01:00
currentKey = reader . ReadElementContentAsString ( ) ;
pairs = new List < NameValuePair > ( ) ;
break ;
case "string" :
var value = reader . ReadElementContentAsString ( ) ;
if ( ! string . IsNullOrWhiteSpace ( value ) )
{
pairs . Add ( new NameValuePair
{
Name = value ,
Value = value
} ) ;
}
2020-06-15 23:43:52 +02:00
2018-12-14 10:40:55 +01:00
break ;
case "array" :
if ( reader . IsEmptyElement )
{
reader . Read ( ) ;
continue ;
}
2020-06-15 23:43:52 +02:00
2018-12-14 10:40:55 +01:00
using ( var subtree = reader . ReadSubtree ( ) )
{
if ( ! string . IsNullOrWhiteSpace ( currentKey ) )
{
pairs . AddRange ( ReadValueArray ( subtree ) ) ;
}
}
2020-06-15 23:43:52 +02:00
2018-12-14 10:40:55 +01:00
break ;
default :
reader . Skip ( ) ;
break ;
}
}
else
{
reader . Read ( ) ;
}
}
}
private List < NameValuePair > ReadValueArray ( XmlReader reader )
{
2019-01-13 21:37:13 +01:00
var pairs = new List < NameValuePair > ( ) ;
2018-12-14 10:40:55 +01:00
reader . MoveToContent ( ) ;
reader . Read ( ) ;
// Loop through each element
while ( ! reader . EOF & & reader . ReadState = = ReadState . Interactive )
{
if ( reader . NodeType = = XmlNodeType . Element )
{
switch ( reader . Name )
{
case "dict" :
if ( reader . IsEmptyElement )
{
reader . Read ( ) ;
continue ;
}
2020-06-15 23:43:52 +02:00
2018-12-14 10:40:55 +01:00
using ( var subtree = reader . ReadSubtree ( ) )
{
var dict = GetNameValuePair ( subtree ) ;
2022-12-05 15:01:13 +01:00
if ( dict is not null )
2018-12-14 10:40:55 +01:00
{
pairs . Add ( dict ) ;
}
}
2020-06-15 23:43:52 +02:00
2018-12-14 10:40:55 +01:00
break ;
default :
reader . Skip ( ) ;
break ;
}
}
else
{
reader . Read ( ) ;
}
}
return pairs ;
}
private void ProcessPairs ( string key , List < NameValuePair > pairs , MediaInfo info )
{
IList < BaseItemPerson > peoples = new List < BaseItemPerson > ( ) ;
if ( string . Equals ( key , "studio" , StringComparison . OrdinalIgnoreCase ) )
{
info . Studios = pairs . Select ( p = > p . Value )
. Where ( i = > ! string . IsNullOrWhiteSpace ( i ) )
. Distinct ( StringComparer . OrdinalIgnoreCase )
. ToArray ( ) ;
}
else if ( string . Equals ( key , "screenwriters" , StringComparison . OrdinalIgnoreCase ) )
{
foreach ( var pair in pairs )
{
peoples . Add ( new BaseItemPerson
{
Name = pair . Value ,
2023-03-25 18:52:02 +01:00
Type = PersonKind . Writer
2018-12-14 10:40:55 +01:00
} ) ;
}
}
else if ( string . Equals ( key , "producers" , StringComparison . OrdinalIgnoreCase ) )
{
foreach ( var pair in pairs )
{
peoples . Add ( new BaseItemPerson
{
Name = pair . Value ,
2023-03-25 18:52:02 +01:00
Type = PersonKind . Producer
2018-12-14 10:40:55 +01:00
} ) ;
}
}
else if ( string . Equals ( key , "directors" , StringComparison . OrdinalIgnoreCase ) )
{
foreach ( var pair in pairs )
{
peoples . Add ( new BaseItemPerson
{
Name = pair . Value ,
2023-03-25 18:52:02 +01:00
Type = PersonKind . Director
2018-12-14 10:40:55 +01:00
} ) ;
}
}
info . People = peoples . ToArray ( ) ;
}
private NameValuePair GetNameValuePair ( XmlReader reader )
{
string name = null ;
string value = null ;
reader . MoveToContent ( ) ;
reader . Read ( ) ;
// Loop through each element
while ( ! reader . EOF & & reader . ReadState = = ReadState . Interactive )
{
if ( reader . NodeType = = XmlNodeType . Element )
{
switch ( reader . Name )
{
case "key" :
name = reader . ReadElementContentAsString ( ) ;
break ;
case "string" :
value = reader . ReadElementContentAsString ( ) ;
break ;
default :
reader . Skip ( ) ;
break ;
}
}
else
{
reader . Read ( ) ;
}
}
2023-02-19 16:52:29 +01:00
if ( string . IsNullOrWhiteSpace ( name )
| | string . IsNullOrWhiteSpace ( value ) )
2018-12-14 10:40:55 +01:00
{
return null ;
}
return new NameValuePair
{
Name = name ,
Value = value
} ;
}
private string NormalizeSubtitleCodec ( string codec )
{
if ( string . Equals ( codec , "dvb_subtitle" , StringComparison . OrdinalIgnoreCase ) )
{
codec = "dvbsub" ;
}
else if ( ( codec ? ? string . Empty ) . IndexOf ( "PGS" , StringComparison . OrdinalIgnoreCase ) ! = - 1 )
{
codec = "PGSSUB" ;
}
else if ( ( codec ? ? string . Empty ) . IndexOf ( "DVD" , StringComparison . OrdinalIgnoreCase ) ! = - 1 )
{
codec = "DVDSUB" ;
}
return codec ;
}
2019-10-03 17:51:28 +02:00
/// <summary>
2020-06-16 00:37:52 +02:00
/// Converts ffprobe stream info to our MediaAttachment class.
2019-10-03 17:51:28 +02:00
/// </summary>
/// <param name="streamInfo">The stream info.</param>
/// <returns>MediaAttachments.</returns>
private MediaAttachment GetMediaAttachment ( MediaStreamInfo streamInfo )
{
2023-02-01 14:58:04 +01:00
if ( streamInfo . CodecType ! = CodecType . Attachment
2021-10-11 21:25:12 +02:00
& & streamInfo . Disposition ? . GetValueOrDefault ( "attached_pic" ) ! = 1 )
2019-10-03 17:51:28 +02:00
{
return null ;
}
var attachment = new MediaAttachment
{
2020-01-08 18:13:11 +01:00
Codec = streamInfo . CodecName ,
Index = streamInfo . Index
2019-10-03 17:51:28 +02:00
} ;
2020-01-08 18:13:11 +01:00
if ( ! string . IsNullOrWhiteSpace ( streamInfo . CodecTagString ) )
2019-10-03 17:51:28 +02:00
{
2020-03-24 16:12:06 +01:00
attachment . CodecTag = streamInfo . CodecTagString ;
2019-10-03 17:51:28 +02:00
}
2022-12-05 15:01:13 +01:00
if ( streamInfo . Tags is not null )
2019-10-03 17:51:28 +02:00
{
2020-01-08 18:13:11 +01:00
attachment . FileName = GetDictionaryValue ( streamInfo . Tags , "filename" ) ;
attachment . MimeType = GetDictionaryValue ( streamInfo . Tags , "mimetype" ) ;
attachment . Comment = GetDictionaryValue ( streamInfo . Tags , "comment" ) ;
2019-10-03 17:51:28 +02:00
}
return attachment ;
}
2018-12-14 10:40:55 +01:00
/// <summary>
2020-06-16 00:37:52 +02:00
/// Converts ffprobe stream info to our MediaStream class.
2018-12-14 10:40:55 +01:00
/// </summary>
/// <param name="isAudio">if set to <c>true</c> [is info].</param>
/// <param name="streamInfo">The stream info.</param>
/// <param name="formatInfo">The format info.</param>
/// <returns>MediaStream.</returns>
private MediaStream GetMediaStream ( bool isAudio , MediaStreamInfo streamInfo , MediaFormatInfo formatInfo )
{
// These are mp4 chapters
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
if ( string . Equals ( streamInfo . CodecName , "mov_text" , StringComparison . OrdinalIgnoreCase ) )
2018-12-14 10:40:55 +01:00
{
// Edit: but these are also sometimes subtitles?
2020-06-14 11:11:11 +02:00
// return null;
2018-12-14 10:40:55 +01:00
}
var stream = new MediaStream
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
Codec = streamInfo . CodecName ,
Profile = streamInfo . Profile ,
Level = streamInfo . Level ,
Index = streamInfo . Index ,
PixelFormat = streamInfo . PixelFormat ,
NalLengthSize = streamInfo . NalLengthSize ,
TimeBase = streamInfo . TimeBase ,
2023-02-01 14:58:04 +01:00
CodecTimeBase = streamInfo . CodecTimeBase ,
IsAVC = streamInfo . IsAvc
2018-12-14 10:40:55 +01:00
} ;
// Filter out junk
2021-03-09 03:04:47 +01:00
if ( ! string . IsNullOrWhiteSpace ( streamInfo . CodecTagString ) & & ! streamInfo . CodecTagString . Contains ( "[0]" , StringComparison . OrdinalIgnoreCase ) )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . CodecTag = streamInfo . CodecTagString ;
2018-12-14 10:40:55 +01:00
}
2022-12-05 15:01:13 +01:00
if ( streamInfo . Tags is not null )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . Language = GetDictionaryValue ( streamInfo . Tags , "language" ) ;
stream . Comment = GetDictionaryValue ( streamInfo . Tags , "comment" ) ;
stream . Title = GetDictionaryValue ( streamInfo . Tags , "title" ) ;
2018-12-14 10:40:55 +01:00
}
2023-02-01 14:58:04 +01:00
if ( streamInfo . CodecType = = CodecType . Audio )
2018-12-14 10:40:55 +01:00
{
stream . Type = MediaStreamType . Audio ;
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . Channels = streamInfo . Channels ;
2018-12-14 10:40:55 +01:00
2023-02-19 16:52:29 +01:00
if ( int . TryParse ( streamInfo . SampleRate , CultureInfo . InvariantCulture , out var sampleRate ) )
2018-12-14 10:40:55 +01:00
{
2023-02-19 16:52:29 +01:00
stream . SampleRate = sampleRate ;
2018-12-14 10:40:55 +01:00
}
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . ChannelLayout = ParseChannelLayout ( streamInfo . ChannelLayout ) ;
2018-12-14 10:40:55 +01:00
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
if ( streamInfo . BitsPerSample > 0 )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . BitDepth = streamInfo . BitsPerSample ;
2018-12-14 10:40:55 +01:00
}
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
else if ( streamInfo . BitsPerRawSample > 0 )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . BitDepth = streamInfo . BitsPerRawSample ;
2018-12-14 10:40:55 +01:00
}
2021-09-30 22:24:46 +02:00
if ( string . IsNullOrEmpty ( stream . Title ) )
{
2022-02-28 17:44:23 +01:00
// mp4 missing track title workaround: fall back to handler_name if populated and not the default "SoundHandler"
2021-09-30 22:24:46 +02:00
string handlerName = GetDictionaryValue ( streamInfo . Tags , "handler_name" ) ;
2022-02-28 17:44:23 +01:00
if ( ! string . IsNullOrEmpty ( handlerName ) & & ! string . Equals ( handlerName , "SoundHandler" , StringComparison . OrdinalIgnoreCase ) )
2021-09-30 22:24:46 +02:00
{
stream . Title = handlerName ;
}
}
2018-12-14 10:40:55 +01:00
}
2023-02-01 14:58:04 +01:00
else if ( streamInfo . CodecType = = CodecType . Subtitle )
2018-12-14 10:40:55 +01:00
{
stream . Type = MediaStreamType . Subtitle ;
stream . Codec = NormalizeSubtitleCodec ( stream . Codec ) ;
2021-02-20 23:13:04 +01:00
stream . LocalizedUndefined = _localization . GetLocalizedString ( "Undefined" ) ;
stream . LocalizedDefault = _localization . GetLocalizedString ( "Default" ) ;
stream . LocalizedForced = _localization . GetLocalizedString ( "Forced" ) ;
2022-03-10 22:20:35 +01:00
stream . LocalizedExternal = _localization . GetLocalizedString ( "External" ) ;
2022-10-07 13:48:31 +02:00
stream . LocalizedHearingImpaired = _localization . GetLocalizedString ( "HearingImpaired" ) ;
2021-09-30 22:24:46 +02:00
if ( string . IsNullOrEmpty ( stream . Title ) )
{
// mp4 missing track title workaround: fall back to handler_name if populated and not the default "SubtitleHandler"
string handlerName = GetDictionaryValue ( streamInfo . Tags , "handler_name" ) ;
if ( ! string . IsNullOrEmpty ( handlerName ) & & ! string . Equals ( handlerName , "SubtitleHandler" , StringComparison . OrdinalIgnoreCase ) )
{
stream . Title = handlerName ;
}
}
2018-12-14 10:40:55 +01:00
}
2023-02-01 14:58:04 +01:00
else if ( streamInfo . CodecType = = CodecType . Video )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . AverageFrameRate = GetFrameRate ( streamInfo . AverageFrameRate ) ;
stream . RealFrameRate = GetFrameRate ( streamInfo . RFrameRate ) ;
2018-12-14 10:40:55 +01:00
2023-01-19 14:19:56 +01:00
stream . IsInterlaced = ! string . IsNullOrWhiteSpace ( streamInfo . FieldOrder )
2022-03-10 20:55:30 +01:00
& & ! string . Equals ( streamInfo . FieldOrder , "progressive" , StringComparison . OrdinalIgnoreCase ) ;
2021-11-12 16:30:30 +01:00
if ( isAudio
2023-08-31 01:19:52 +02:00
& & ( string . Equals ( stream . Codec , "bmp" , StringComparison . OrdinalIgnoreCase )
| | string . Equals ( stream . Codec , "gif" , StringComparison . OrdinalIgnoreCase )
| | string . Equals ( stream . Codec , "mjpeg" , StringComparison . OrdinalIgnoreCase )
| | string . Equals ( stream . Codec , "png" , StringComparison . OrdinalIgnoreCase )
| | string . Equals ( stream . Codec , "webp" , StringComparison . OrdinalIgnoreCase ) ) )
2018-12-14 10:40:55 +01:00
{
stream . Type = MediaStreamType . EmbeddedImage ;
}
else if ( string . Equals ( stream . Codec , "mjpeg" , StringComparison . OrdinalIgnoreCase ) )
{
// How to differentiate between video and embedded image?
2021-10-07 22:37:59 +02:00
// The only difference I've seen thus far is presence of codec tag, also embedded images have high (unusual) framerates
if ( ! string . IsNullOrWhiteSpace ( stream . CodecTag ) )
2018-12-14 10:40:55 +01:00
{
2021-10-07 22:37:59 +02:00
stream . Type = MediaStreamType . Video ;
2018-12-14 10:40:55 +01:00
}
else
{
2021-10-07 22:37:59 +02:00
stream . Type = MediaStreamType . EmbeddedImage ;
2018-12-14 10:40:55 +01:00
}
}
else
{
stream . Type = MediaStreamType . Video ;
}
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . Width = streamInfo . Width ;
stream . Height = streamInfo . Height ;
2018-12-14 10:40:55 +01:00
stream . AspectRatio = GetAspectRatio ( streamInfo ) ;
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
if ( streamInfo . BitsPerSample > 0 )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . BitDepth = streamInfo . BitsPerSample ;
2018-12-14 10:40:55 +01:00
}
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
else if ( streamInfo . BitsPerRawSample > 0 )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . BitDepth = streamInfo . BitsPerRawSample ;
2018-12-14 10:40:55 +01:00
}
2021-07-24 18:52:16 +02:00
if ( ! stream . BitDepth . HasValue )
{
2021-12-01 17:49:50 +01:00
if ( ! string . IsNullOrEmpty ( streamInfo . PixelFormat ) )
2021-07-24 18:52:16 +02:00
{
2021-12-01 17:49:50 +01:00
if ( string . Equals ( streamInfo . PixelFormat , "yuv420p" , StringComparison . OrdinalIgnoreCase )
| | string . Equals ( streamInfo . PixelFormat , "yuv444p" , StringComparison . OrdinalIgnoreCase ) )
{
stream . BitDepth = 8 ;
}
else if ( string . Equals ( streamInfo . PixelFormat , "yuv420p10le" , StringComparison . OrdinalIgnoreCase )
2021-12-24 09:50:40 +01:00
| | string . Equals ( streamInfo . PixelFormat , "yuv444p10le" , StringComparison . OrdinalIgnoreCase ) )
2021-12-01 17:49:50 +01:00
{
stream . BitDepth = 10 ;
}
else if ( string . Equals ( streamInfo . PixelFormat , "yuv420p12le" , StringComparison . OrdinalIgnoreCase )
2021-12-24 09:50:40 +01:00
| | string . Equals ( streamInfo . PixelFormat , "yuv444p12le" , StringComparison . OrdinalIgnoreCase ) )
2021-12-01 17:49:50 +01:00
{
stream . BitDepth = 12 ;
}
2021-07-24 18:52:16 +02:00
}
}
2020-06-14 11:11:11 +02:00
// stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase) ||
2018-12-14 10:40:55 +01:00
// string.Equals(stream.AspectRatio, "2.35:1", StringComparison.OrdinalIgnoreCase) ||
// string.Equals(stream.AspectRatio, "2.40:1", StringComparison.OrdinalIgnoreCase);
// http://stackoverflow.com/questions/17353387/how-to-detect-anamorphic-video-with-ffprobe
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . IsAnamorphic = string . Equals ( streamInfo . SampleAspectRatio , "0:1" , StringComparison . OrdinalIgnoreCase ) ;
2018-12-14 10:40:55 +01:00
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
if ( streamInfo . Refs > 0 )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
stream . RefFrames = streamInfo . Refs ;
2018-12-14 10:40:55 +01:00
}
2020-05-14 18:11:32 +02:00
2020-07-24 18:57:34 +02:00
if ( ! string . IsNullOrEmpty ( streamInfo . ColorRange ) )
{
stream . ColorRange = streamInfo . ColorRange ;
}
if ( ! string . IsNullOrEmpty ( streamInfo . ColorSpace ) )
{
stream . ColorSpace = streamInfo . ColorSpace ;
}
2020-05-14 18:11:32 +02:00
if ( ! string . IsNullOrEmpty ( streamInfo . ColorTransfer ) )
{
stream . ColorTransfer = streamInfo . ColorTransfer ;
}
2020-05-14 18:52:42 +02:00
if ( ! string . IsNullOrEmpty ( streamInfo . ColorPrimaries ) )
{
stream . ColorPrimaries = streamInfo . ColorPrimaries ;
}
2022-06-27 02:55:36 +02:00
2022-12-05 15:01:13 +01:00
if ( streamInfo . SideDataList is not null )
2022-06-27 02:55:36 +02:00
{
foreach ( var data in streamInfo . SideDataList )
{
// Parse Dolby Vision metadata from side_data
if ( string . Equals ( data . SideDataType , "DOVI configuration record" , StringComparison . OrdinalIgnoreCase ) )
{
stream . DvVersionMajor = data . DvVersionMajor ;
stream . DvVersionMinor = data . DvVersionMinor ;
stream . DvProfile = data . DvProfile ;
stream . DvLevel = data . DvLevel ;
stream . RpuPresentFlag = data . RpuPresentFlag ;
stream . ElPresentFlag = data . ElPresentFlag ;
stream . BlPresentFlag = data . BlPresentFlag ;
stream . DvBlSignalCompatibilityId = data . DvBlSignalCompatibilityId ;
break ;
}
}
}
2018-12-14 10:40:55 +01:00
}
2023-02-01 14:58:04 +01:00
else if ( streamInfo . CodecType = = CodecType . Data )
2022-10-01 16:53:54 +02:00
{
stream . Type = MediaStreamType . Data ;
}
2018-12-14 10:40:55 +01:00
else
{
return null ;
}
// Get stream bitrate
var bitrate = 0 ;
2023-02-19 16:52:29 +01:00
if ( int . TryParse ( streamInfo . BitRate , CultureInfo . InvariantCulture , out var value ) )
2018-12-14 10:40:55 +01:00
{
2023-02-19 16:52:29 +01:00
bitrate = value ;
2018-12-14 10:40:55 +01:00
}
2020-11-29 15:46:26 +01:00
// The bitrate info of FLAC musics and some videos is included in formatInfo.
if ( bitrate = = 0
2022-12-05 15:01:13 +01:00
& & formatInfo is not null
2020-12-01 03:53:56 +01:00
& & ( stream . Type = = MediaStreamType . Video | | ( isAudio & & stream . Type = = MediaStreamType . Audio ) ) )
2018-12-14 10:40:55 +01:00
{
// If the stream info doesn't have a bitrate get the value from the media format info
2023-02-19 16:52:29 +01:00
if ( int . TryParse ( formatInfo . BitRate , CultureInfo . InvariantCulture , out value ) )
2018-12-14 10:40:55 +01:00
{
bitrate = value ;
}
}
if ( bitrate > 0 )
{
stream . BitRate = bitrate ;
}
2020-11-11 10:08:50 +01:00
// Extract bitrate info from tag "BPS" if possible.
if ( ! stream . BitRate . HasValue
2023-02-01 14:58:04 +01:00
& & ( streamInfo . CodecType = = CodecType . Audio
| | streamInfo . CodecType = = CodecType . Video ) )
2020-11-11 10:08:50 +01:00
{
var bps = GetBPSFromTags ( streamInfo ) ;
2021-07-09 02:06:38 +02:00
if ( bps > 0 )
2020-11-11 10:08:50 +01:00
{
stream . BitRate = bps ;
}
2023-02-01 14:58:04 +01:00
else
2020-11-11 10:08:50 +01:00
{
2023-02-01 14:58:04 +01:00
// Get average bitrate info from tag "NUMBER_OF_BYTES" and "DURATION" if possible.
var durationInSeconds = GetRuntimeSecondsFromTags ( streamInfo ) ;
var bytes = GetNumberOfBytesFromTags ( streamInfo ) ;
if ( durationInSeconds is not null & & bytes is not null )
2020-11-11 10:08:50 +01:00
{
2023-02-01 14:58:04 +01:00
bps = Convert . ToInt32 ( bytes * 8 / durationInSeconds , CultureInfo . InvariantCulture ) ;
if ( bps > 0 )
{
stream . BitRate = bps ;
}
2020-11-11 10:08:50 +01:00
}
}
}
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
var disposition = streamInfo . Disposition ;
2022-12-05 15:01:13 +01:00
if ( disposition is not null )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
if ( disposition . GetValueOrDefault ( "default" ) = = 1 )
{
stream . IsDefault = true ;
}
2018-12-14 10:40:55 +01:00
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
if ( disposition . GetValueOrDefault ( "forced" ) = = 1 )
{
stream . IsForced = true ;
}
2022-10-07 12:38:05 +02:00
if ( disposition . GetValueOrDefault ( "hearing_impaired" ) = = 1 )
{
stream . IsHearingImpaired = true ;
}
2018-12-14 10:40:55 +01:00
}
NormalizeStreamTitle ( stream ) ;
return stream ;
}
private void NormalizeStreamTitle ( MediaStream stream )
{
2023-02-01 14:58:04 +01:00
if ( string . Equals ( stream . Title , "cc" , StringComparison . OrdinalIgnoreCase )
| | stream . Type = = MediaStreamType . EmbeddedImage )
2018-12-14 10:40:55 +01:00
{
stream . Title = null ;
}
}
/// <summary>
2020-06-16 00:37:52 +02:00
/// Gets a string from an FFProbeResult tags dictionary.
2018-12-14 10:40:55 +01:00
/// </summary>
/// <param name="tags">The tags.</param>
/// <param name="key">The key.</param>
/// <returns>System.String.</returns>
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
private string GetDictionaryValue ( IReadOnlyDictionary < string , string > tags , string key )
2018-12-14 10:40:55 +01:00
{
2022-12-05 15:00:20 +01:00
if ( tags is null )
2018-12-14 10:40:55 +01:00
{
return null ;
}
2019-01-13 21:46:33 +01:00
tags . TryGetValue ( key , out var val ) ;
2021-07-09 02:06:38 +02:00
2018-12-14 10:40:55 +01:00
return val ;
}
private string ParseChannelLayout ( string input )
{
if ( string . IsNullOrEmpty ( input ) )
{
2021-07-09 02:06:38 +02:00
return null ;
2018-12-14 10:40:55 +01:00
}
2023-02-01 14:58:04 +01:00
return input . AsSpan ( ) . LeftPart ( '(' ) . ToString ( ) ;
2018-12-14 10:40:55 +01:00
}
private string GetAspectRatio ( MediaStreamInfo info )
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
var original = info . DisplayAspectRatio ;
2018-12-14 10:40:55 +01:00
var parts = ( original ? ? string . Empty ) . Split ( ':' ) ;
2023-02-01 14:58:04 +01:00
if ( ! ( parts . Length = = 2
2023-02-19 16:52:29 +01:00
& & int . TryParse ( parts [ 0 ] , CultureInfo . InvariantCulture , out var width )
& & int . TryParse ( parts [ 1 ] , CultureInfo . InvariantCulture , out var height )
2023-02-01 14:58:04 +01:00
& & width > 0
& & height > 0 ) )
2018-12-14 10:40:55 +01:00
{
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
width = info . Width ;
height = info . Height ;
2018-12-14 10:40:55 +01:00
}
if ( width > 0 & & height > 0 )
{
double ratio = width ;
ratio / = height ;
if ( IsClose ( ratio , 1.777777778 , . 03 ) )
{
return "16:9" ;
}
if ( IsClose ( ratio , 1.3333333333 , . 05 ) )
{
return "4:3" ;
}
if ( IsClose ( ratio , 1.41 ) )
{
return "1.41:1" ;
}
if ( IsClose ( ratio , 1.5 ) )
{
return "1.5:1" ;
}
if ( IsClose ( ratio , 1.6 ) )
{
return "1.6:1" ;
}
if ( IsClose ( ratio , 1.66666666667 ) )
{
return "5:3" ;
}
if ( IsClose ( ratio , 1.85 , . 02 ) )
{
return "1.85:1" ;
}
if ( IsClose ( ratio , 2.35 , . 025 ) )
{
return "2.35:1" ;
}
if ( IsClose ( ratio , 2.4 , . 025 ) )
{
return "2.40:1" ;
}
}
return original ;
}
private bool IsClose ( double d1 , double d2 , double variance = . 005 )
{
return Math . Abs ( d1 - d2 ) < = variance ;
}
/// <summary>
/// Gets a frame rate from a string value in ffprobe output
/// This could be a number or in the format of 2997/125.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>System.Nullable{System.Single}.</returns>
2021-12-12 02:22:30 +01:00
internal static float? GetFrameRate ( ReadOnlySpan < char > value )
2018-12-14 10:40:55 +01:00
{
2021-12-12 02:22:30 +01:00
if ( value . IsEmpty )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
return null ;
}
2018-12-14 10:40:55 +01:00
2021-12-12 02:22:30 +01:00
int index = value . IndexOf ( '/' ) ;
if ( index = = - 1 )
2021-07-09 02:06:38 +02:00
{
2021-12-12 02:22:30 +01:00
return null ;
2021-07-09 02:06:38 +02:00
}
2021-12-12 02:22:30 +01:00
if ( ! float . TryParse ( value [ . . index ] , NumberStyles . Integer , CultureInfo . InvariantCulture , out var dividend )
| | ! float . TryParse ( value [ ( index + 1 ) . . ] , NumberStyles . Integer , CultureInfo . InvariantCulture , out var divisor ) )
2021-07-09 02:06:38 +02:00
{
2021-12-12 02:22:30 +01:00
return null ;
2018-12-14 10:40:55 +01:00
}
2021-12-15 18:33:27 +01:00
return divisor = = 0f ? null : dividend / divisor ;
2018-12-14 10:40:55 +01:00
}
private void SetAudioRuntimeTicks ( InternalMediaInfoResult result , MediaInfo data )
{
2021-07-09 02:06:38 +02:00
// Get the first info stream
2023-02-01 14:58:04 +01:00
var stream = result . Streams ? . FirstOrDefault ( s = > s . CodecType = = CodecType . Audio ) ;
2022-12-05 15:00:20 +01:00
if ( stream is null )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
return ;
}
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
// Get duration from stream properties
var duration = stream . Duration ;
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
// If it's not there go into format properties
if ( string . IsNullOrEmpty ( duration ) )
{
duration = result . Format . Duration ;
}
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
// If we got something, parse it
if ( ! string . IsNullOrEmpty ( duration ) )
{
2021-09-26 16:14:36 +02:00
data . RunTimeTicks = TimeSpan . FromSeconds ( double . Parse ( duration , CultureInfo . InvariantCulture ) ) . Ticks ;
2018-12-14 10:40:55 +01:00
}
}
2020-11-11 10:08:50 +01:00
private int? GetBPSFromTags ( MediaStreamInfo streamInfo )
{
2022-12-05 15:00:20 +01:00
if ( streamInfo ? . Tags is null )
2020-11-11 10:08:50 +01:00
{
2021-07-09 02:06:38 +02:00
return null ;
}
var bps = GetDictionaryValue ( streamInfo . Tags , "BPS-eng" ) ? ? GetDictionaryValue ( streamInfo . Tags , "BPS" ) ;
2023-02-01 14:58:04 +01:00
if ( int . TryParse ( bps , NumberStyles . Integer , CultureInfo . InvariantCulture , out var parsedBps ) )
2021-07-09 02:06:38 +02:00
{
return parsedBps ;
2020-11-11 10:08:50 +01:00
}
return null ;
}
private double? GetRuntimeSecondsFromTags ( MediaStreamInfo streamInfo )
{
2022-12-05 15:00:20 +01:00
if ( streamInfo ? . Tags is null )
2020-11-11 10:08:50 +01:00
{
2021-07-09 02:06:38 +02:00
return null ;
}
var duration = GetDictionaryValue ( streamInfo . Tags , "DURATION-eng" ) ? ? GetDictionaryValue ( streamInfo . Tags , "DURATION" ) ;
2023-02-19 16:52:29 +01:00
if ( TimeSpan . TryParse ( duration , out var parsedDuration ) )
2021-07-09 02:06:38 +02:00
{
return parsedDuration . TotalSeconds ;
2020-11-11 10:08:50 +01:00
}
return null ;
}
private long? GetNumberOfBytesFromTags ( MediaStreamInfo streamInfo )
{
2022-12-05 15:00:20 +01:00
if ( streamInfo ? . Tags is null )
2020-11-11 10:08:50 +01:00
{
2021-07-09 02:06:38 +02:00
return null ;
}
var numberOfBytes = GetDictionaryValue ( streamInfo . Tags , "NUMBER_OF_BYTES-eng" )
? ? GetDictionaryValue ( streamInfo . Tags , "NUMBER_OF_BYTES" ) ;
2023-02-01 14:58:04 +01:00
if ( long . TryParse ( numberOfBytes , NumberStyles . Integer , CultureInfo . InvariantCulture , out var parsedBytes ) )
2021-07-09 02:06:38 +02:00
{
return parsedBytes ;
2020-11-11 10:08:50 +01:00
}
return null ;
}
2019-01-13 21:37:13 +01:00
private void SetSize ( InternalMediaInfoResult data , MediaInfo info )
2018-12-14 10:40:55 +01:00
{
2022-12-05 15:00:20 +01:00
if ( data . Format is null )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
return ;
2018-12-14 10:40:55 +01:00
}
2021-07-09 02:06:38 +02:00
2021-09-26 16:14:36 +02:00
info . Size = string . IsNullOrEmpty ( data . Format . Size ) ? null : long . Parse ( data . Format . Size , CultureInfo . InvariantCulture ) ;
2018-12-14 10:40:55 +01:00
}
2021-07-09 02:06:38 +02:00
private void SetAudioInfoFromTags ( MediaInfo audio , IReadOnlyDictionary < string , string > tags )
2018-12-14 10:40:55 +01:00
{
2021-04-04 23:34:29 +02:00
var people = new List < BaseItemPerson > ( ) ;
2021-07-09 02:06:38 +02:00
if ( tags . TryGetValue ( "composer" , out var composer ) & & ! string . IsNullOrWhiteSpace ( composer ) )
2018-12-14 10:40:55 +01:00
{
foreach ( var person in Split ( composer , false ) )
{
2023-03-25 18:52:02 +01:00
people . Add ( new BaseItemPerson { Name = person , Type = PersonKind . Composer } ) ;
2018-12-14 10:40:55 +01:00
}
}
2021-07-09 02:06:38 +02:00
if ( tags . TryGetValue ( "conductor" , out var conductor ) & & ! string . IsNullOrWhiteSpace ( conductor ) )
2020-08-04 17:08:09 +02:00
{
foreach ( var person in Split ( conductor , false ) )
{
2023-03-25 18:52:02 +01:00
people . Add ( new BaseItemPerson { Name = person , Type = PersonKind . Conductor } ) ;
2020-08-04 17:08:09 +02:00
}
}
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
if ( tags . TryGetValue ( "lyricist" , out var lyricist ) & & ! string . IsNullOrWhiteSpace ( lyricist ) )
2020-08-04 17:08:09 +02:00
{
foreach ( var person in Split ( lyricist , false ) )
{
2023-03-25 18:52:02 +01:00
people . Add ( new BaseItemPerson { Name = person , Type = PersonKind . Lyricist } ) ;
2020-08-04 17:08:09 +02:00
}
}
2018-12-14 10:40:55 +01:00
2021-07-27 17:09:23 +02:00
if ( tags . TryGetValue ( "performer" , out var performer ) & & ! string . IsNullOrWhiteSpace ( performer ) )
{
foreach ( var person in Split ( performer , false ) )
{
2021-08-02 03:48:45 +02:00
Match match = _performerPattern . Match ( person ) ;
2021-07-27 17:09:23 +02:00
// If the performer doesn't have any instrument/role associated, it won't match. In that case, chances are it's simply a band name, so we skip it.
if ( match . Success )
{
people . Add ( new BaseItemPerson
{
Name = match . Groups [ "name" ] . Value ,
2023-03-25 18:52:02 +01:00
Type = PersonKind . Actor ,
2021-09-26 16:14:36 +02:00
Role = CultureInfo . InvariantCulture . TextInfo . ToTitleCase ( match . Groups [ "instrument" ] . Value )
2021-07-27 17:09:23 +02:00
} ) ;
}
}
}
2021-07-27 23:52:05 +02:00
// In cases where there isn't sufficient information as to which role a writer performed on a recording, tagging software uses the "writer" tag.
2021-07-09 02:06:38 +02:00
if ( tags . TryGetValue ( "writer" , out var writer ) & & ! string . IsNullOrWhiteSpace ( writer ) )
2018-12-14 10:40:55 +01:00
{
foreach ( var person in Split ( writer , false ) )
{
2023-03-25 18:52:02 +01:00
people . Add ( new BaseItemPerson { Name = person , Type = PersonKind . Writer } ) ;
2018-12-14 10:40:55 +01:00
}
}
2021-07-27 23:52:05 +02:00
if ( tags . TryGetValue ( "arranger" , out var arranger ) & & ! string . IsNullOrWhiteSpace ( arranger ) )
{
foreach ( var person in Split ( arranger , false ) )
{
2023-03-25 18:52:02 +01:00
people . Add ( new BaseItemPerson { Name = person , Type = PersonKind . Arranger } ) ;
2021-07-27 23:52:05 +02:00
}
}
if ( tags . TryGetValue ( "engineer" , out var engineer ) & & ! string . IsNullOrWhiteSpace ( engineer ) )
{
foreach ( var person in Split ( engineer , false ) )
{
2023-03-25 18:52:02 +01:00
people . Add ( new BaseItemPerson { Name = person , Type = PersonKind . Engineer } ) ;
2021-07-27 23:52:05 +02:00
}
}
if ( tags . TryGetValue ( "mixer" , out var mixer ) & & ! string . IsNullOrWhiteSpace ( mixer ) )
{
foreach ( var person in Split ( mixer , false ) )
{
2023-03-25 18:52:02 +01:00
people . Add ( new BaseItemPerson { Name = person , Type = PersonKind . Mixer } ) ;
2021-07-27 23:52:05 +02:00
}
}
if ( tags . TryGetValue ( "remixer" , out var remixer ) & & ! string . IsNullOrWhiteSpace ( remixer ) )
{
foreach ( var person in Split ( remixer , false ) )
{
2023-03-25 18:52:02 +01:00
people . Add ( new BaseItemPerson { Name = person , Type = PersonKind . Remixer } ) ;
2021-07-27 23:52:05 +02:00
}
}
2021-04-04 23:34:29 +02:00
audio . People = people . ToArray ( ) ;
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
// Set album artist
var albumArtist = tags . GetFirstNotNullNorWhiteSpaceValue ( "albumartist" , "album artist" , "album_artist" ) ;
2022-12-05 15:01:13 +01:00
audio . AlbumArtists = albumArtist is not null
2021-07-09 02:06:38 +02:00
? SplitDistinctArtists ( albumArtist , _nameDelimiters , true ) . ToArray ( )
: Array . Empty < string > ( ) ;
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
// Set album artist to artist if empty
2018-12-14 10:40:55 +01:00
if ( audio . AlbumArtists . Length = = 0 )
{
audio . AlbumArtists = audio . Artists ;
}
// Track number
2021-07-09 02:06:38 +02:00
audio . IndexNumber = GetDictionaryTrackOrDiscNumber ( tags , "track" ) ;
2018-12-14 10:40:55 +01:00
// Disc number
2021-07-09 02:06:38 +02:00
audio . ParentIndexNumber = GetDictionaryTrackOrDiscNumber ( tags , "disc" ) ;
2018-12-14 10:40:55 +01:00
// There's several values in tags may or may not be present
FetchStudios ( audio , tags , "organization" ) ;
FetchStudios ( audio , tags , "ensemble" ) ;
FetchStudios ( audio , tags , "publisher" ) ;
FetchStudios ( audio , tags , "label" ) ;
2021-07-09 02:06:38 +02:00
// These support multiple values, but for now we only store the first.
var mb = GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MusicBrainz Album Artist Id" ) )
? ? GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MUSICBRAINZ_ALBUMARTISTID" ) ) ;
2020-06-06 21:17:49 +02:00
audio . SetProviderId ( MetadataProvider . MusicBrainzAlbumArtist , mb ) ;
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
mb = GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MusicBrainz Artist Id" ) )
? ? GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MUSICBRAINZ_ARTISTID" ) ) ;
2020-06-06 21:17:49 +02:00
audio . SetProviderId ( MetadataProvider . MusicBrainzArtist , mb ) ;
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
mb = GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MusicBrainz Album Id" ) )
? ? GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MUSICBRAINZ_ALBUMID" ) ) ;
2020-06-06 21:17:49 +02:00
audio . SetProviderId ( MetadataProvider . MusicBrainzAlbum , mb ) ;
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
mb = GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MusicBrainz Release Group Id" ) )
? ? GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MUSICBRAINZ_RELEASEGROUPID" ) ) ;
2020-06-06 21:17:49 +02:00
audio . SetProviderId ( MetadataProvider . MusicBrainzReleaseGroup , mb ) ;
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
mb = GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MusicBrainz Release Track Id" ) )
? ? GetMultipleMusicBrainzId ( tags . GetValueOrDefault ( "MUSICBRAINZ_RELEASETRACKID" ) ) ;
2020-06-06 21:17:49 +02:00
audio . SetProviderId ( MetadataProvider . MusicBrainzTrack , mb ) ;
2018-12-14 10:40:55 +01:00
}
private string GetMultipleMusicBrainzId ( string value )
{
if ( string . IsNullOrWhiteSpace ( value ) )
{
return null ;
}
2020-11-14 16:28:49 +01:00
return value . Split ( '/' , StringSplitOptions . RemoveEmptyEntries )
2018-12-14 10:40:55 +01:00
. Select ( i = > i . Trim ( ) )
. FirstOrDefault ( i = > ! string . IsNullOrWhiteSpace ( i ) ) ;
}
/// <summary>
/// Splits the specified val.
/// </summary>
/// <param name="val">The val.</param>
/// <param name="allowCommaDelimiter">if set to <c>true</c> [allow comma delimiter].</param>
/// <returns>System.String[][].</returns>
private IEnumerable < string > Split ( string val , bool allowCommaDelimiter )
{
2021-07-09 02:06:38 +02:00
// Only use the comma as a delimiter if there are no slashes or pipes.
2018-12-14 10:40:55 +01:00
// We want to be careful not to split names that have commas in them
2021-07-09 02:06:38 +02:00
var delimiter = ! allowCommaDelimiter | | _nameDelimiters . Any ( i = > val . IndexOf ( i , StringComparison . Ordinal ) ! = - 1 ) ?
2018-12-14 10:40:55 +01:00
_nameDelimiters :
new [ ] { ',' } ;
2021-07-09 02:06:38 +02:00
return val . Split ( delimiter , StringSplitOptions . RemoveEmptyEntries )
2018-12-14 10:40:55 +01:00
. Where ( i = > ! string . IsNullOrWhiteSpace ( i ) )
. Select ( i = > i . Trim ( ) ) ;
}
2021-07-09 02:06:38 +02:00
private IEnumerable < string > SplitDistinctArtists ( string val , char [ ] delimiters , bool splitFeaturing )
2018-12-14 10:40:55 +01:00
{
if ( splitFeaturing )
{
val = val . Replace ( " featuring " , ArtistReplaceValue , StringComparison . OrdinalIgnoreCase )
. Replace ( " feat. " , ArtistReplaceValue , StringComparison . OrdinalIgnoreCase ) ;
}
var artistsFound = new List < string > ( ) ;
2021-05-05 14:39:50 +02:00
foreach ( var whitelistArtist in SplitWhitelist )
2018-12-14 10:40:55 +01:00
{
var originalVal = val ;
val = val . Replace ( whitelistArtist , "|" , StringComparison . OrdinalIgnoreCase ) ;
if ( ! string . Equals ( originalVal , val , StringComparison . OrdinalIgnoreCase ) )
{
artistsFound . Add ( whitelistArtist ) ;
}
}
var artists = val . Split ( delimiters , StringSplitOptions . RemoveEmptyEntries )
. Where ( i = > ! string . IsNullOrWhiteSpace ( i ) )
. Select ( i = > i . Trim ( ) ) ;
artistsFound . AddRange ( artists ) ;
2021-07-09 02:06:38 +02:00
return artistsFound . DistinctNames ( ) ;
2018-12-14 10:40:55 +01:00
}
/// <summary>
2020-06-16 00:37:52 +02:00
/// Gets the studios from the tags collection.
2018-12-14 10:40:55 +01:00
/// </summary>
/// <param name="info">The info.</param>
/// <param name="tags">The tags.</param>
/// <param name="tagName">Name of the tag.</param>
2021-07-09 02:06:38 +02:00
private void FetchStudios ( MediaInfo info , IReadOnlyDictionary < string , string > tags , string tagName )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
var val = tags . GetValueOrDefault ( tagName ) ;
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
if ( string . IsNullOrEmpty ( val ) )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
return ;
}
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
var studios = Split ( val , true ) ;
var studioList = new List < string > ( ) ;
2020-06-15 23:43:52 +02:00
2021-07-09 02:06:38 +02:00
foreach ( var studio in studios )
{
if ( string . IsNullOrWhiteSpace ( studio ) )
{
continue ;
}
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
// Don't add artist/album artist name to studios, even if it's listed there
2021-12-20 13:31:07 +01:00
if ( info . Artists . Contains ( studio , StringComparison . OrdinalIgnoreCase )
| | info . AlbumArtists . Contains ( studio , StringComparison . OrdinalIgnoreCase ) )
2021-07-09 02:06:38 +02:00
{
continue ;
2018-12-14 10:40:55 +01:00
}
2021-07-09 02:06:38 +02:00
studioList . Add ( studio ) ;
2018-12-14 10:40:55 +01:00
}
2021-07-09 02:06:38 +02:00
info . Studios = studioList
. Distinct ( StringComparer . OrdinalIgnoreCase )
. ToArray ( ) ;
2018-12-14 10:40:55 +01:00
}
/// <summary>
2020-06-16 00:37:52 +02:00
/// Gets the genres from the tags collection.
2018-12-14 10:40:55 +01:00
/// </summary>
/// <param name="info">The information.</param>
/// <param name="tags">The tags.</param>
2021-07-09 02:06:38 +02:00
private void FetchGenres ( MediaInfo info , IReadOnlyDictionary < string , string > tags )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
var genreVal = tags . GetValueOrDefault ( "genre" ) ;
if ( string . IsNullOrEmpty ( genreVal ) )
{
return ;
}
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
var genres = new List < string > ( info . Genres ) ;
foreach ( var genre in Split ( genreVal , true ) )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
if ( string . IsNullOrWhiteSpace ( genre ) )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
continue ;
2018-12-14 10:40:55 +01:00
}
2021-07-09 02:06:38 +02:00
genres . Add ( genre ) ;
2018-12-14 10:40:55 +01:00
}
2021-07-09 02:06:38 +02:00
info . Genres = genres
. Distinct ( StringComparer . OrdinalIgnoreCase )
. ToArray ( ) ;
2018-12-14 10:40:55 +01:00
}
/// <summary>
2021-07-09 02:06:38 +02:00
/// Gets the track or disc number, which can be in the form of '1', or '1/3'.
2018-12-14 10:40:55 +01:00
/// </summary>
/// <param name="tags">The tags.</param>
/// <param name="tagName">Name of the tag.</param>
2021-07-09 02:06:38 +02:00
/// <returns>The track or disc number, or null, if missing or not parseable.</returns>
private static int? GetDictionaryTrackOrDiscNumber ( IReadOnlyDictionary < string , string > tags , string tagName )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
var disc = tags . GetValueOrDefault ( tagName ) ;
2018-12-14 10:40:55 +01:00
2023-02-01 14:58:04 +01:00
if ( int . TryParse ( disc . AsSpan ( ) . LeftPart ( '/' ) , out var discNum ) )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
return discNum ;
2018-12-14 10:40:55 +01:00
}
return null ;
}
2021-07-09 02:06:38 +02:00
private static ChapterInfo GetChapterInfo ( MediaChapter chapter )
2018-12-14 10:40:55 +01:00
{
var info = new ChapterInfo ( ) ;
2022-12-05 15:01:13 +01:00
if ( chapter . Tags is not null & & chapter . Tags . TryGetValue ( "title" , out string name ) )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
info . Name = name ;
2018-12-14 10:40:55 +01:00
}
// Limit accuracy to milliseconds to match xml saving
Fix exceptions while scanning
Fixes these exceptions:
```
[2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.GetWaitState()
at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785
[2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process
[2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process
System.InvalidOperationException: No process is associated with this object.
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.Kill()
at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799
[2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe"
System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399
at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122
at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815
```
2019-12-22 21:39:26 +01:00
var secondsString = chapter . StartTime ;
2018-12-14 10:40:55 +01:00
2023-02-19 16:52:29 +01:00
if ( double . TryParse ( secondsString , CultureInfo . InvariantCulture , out var seconds ) )
2018-12-14 10:40:55 +01:00
{
var ms = Math . Round ( TimeSpan . FromSeconds ( seconds ) . TotalMilliseconds ) ;
info . StartPositionTicks = TimeSpan . FromMilliseconds ( ms ) . Ticks ;
}
return info ;
}
private void FetchWtvInfo ( MediaInfo video , InternalMediaInfoResult data )
{
2021-07-09 02:06:38 +02:00
var tags = data . Format ? . Tags ;
2022-12-05 15:00:20 +01:00
if ( tags is null )
2018-12-14 10:40:55 +01:00
{
return ;
}
2021-07-09 02:06:38 +02:00
if ( tags . TryGetValue ( "WM/Genre" , out var genres ) & & ! string . IsNullOrWhiteSpace ( genres ) )
2018-12-14 10:40:55 +01:00
{
var genreList = genres . Split ( new [ ] { ';' , '/' , ',' } , StringSplitOptions . RemoveEmptyEntries )
. Where ( i = > ! string . IsNullOrWhiteSpace ( i ) )
. Select ( i = > i . Trim ( ) )
. ToList ( ) ;
// If this is empty then don't overwrite genres that might have been fetched earlier
if ( genreList . Count > 0 )
{
video . Genres = genreList . ToArray ( ) ;
}
}
2021-07-09 02:06:38 +02:00
if ( tags . TryGetValue ( "WM/ParentalRating" , out var officialRating ) & & ! string . IsNullOrWhiteSpace ( officialRating ) )
2018-12-14 10:40:55 +01:00
{
video . OfficialRating = officialRating ;
}
2021-07-09 02:06:38 +02:00
if ( tags . TryGetValue ( "WM/MediaCredits" , out var people ) & & ! string . IsNullOrEmpty ( people ) )
2018-12-14 10:40:55 +01:00
{
video . People = people . Split ( new [ ] { ';' , '/' } , StringSplitOptions . RemoveEmptyEntries )
. Where ( i = > ! string . IsNullOrWhiteSpace ( i ) )
2023-03-25 18:52:02 +01:00
. Select ( i = > new BaseItemPerson { Name = i . Trim ( ) , Type = PersonKind . Actor } )
2018-12-14 10:40:55 +01:00
. ToArray ( ) ;
}
2021-09-26 16:14:36 +02:00
if ( tags . TryGetValue ( "WM/OriginalReleaseTime" , out var year ) & & int . TryParse ( year , NumberStyles . Integer , CultureInfo . InvariantCulture , out var parsedYear ) )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
video . ProductionYear = parsedYear ;
2018-12-14 10:40:55 +01:00
}
2021-07-09 02:06:38 +02:00
// Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/
// DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None)
2021-09-21 01:21:45 +02:00
if ( tags . TryGetValue ( "WM/MediaOriginalBroadcastDateTime" , out var premiereDateString ) & & DateTime . TryParse ( year , null , DateTimeStyles . AdjustToUniversal , out var parsedDate ) )
2018-12-14 10:40:55 +01:00
{
2021-09-21 01:21:45 +02:00
video . PremiereDate = parsedDate ;
2018-12-14 10:40:55 +01:00
}
2021-07-09 02:06:38 +02:00
var description = tags . GetValueOrDefault ( "WM/SubTitleDescription" ) ;
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
var subTitle = tags . GetValueOrDefault ( "WM/SubTitle" ) ;
2018-12-14 10:40:55 +01:00
// For below code, credit to MCEBuddy: https://mcebuddy2x.codeplex.com/
// Sometimes for TV Shows the Subtitle field is empty and the subtitle description contains the subtitle, extract if possible. See ticket https://mcebuddy2x.codeplex.com/workitem/1910
// The format is -> EPISODE/TOTAL_EPISODES_IN_SEASON. SUBTITLE: DESCRIPTION
// OR -> COMMENT. SUBTITLE: DESCRIPTION
// e.g. -> 4/13. The Doctor's Wife: Science fiction drama. When he follows a Time Lord distress signal, the Doctor puts Amy, Rory and his beloved TARDIS in grave danger. Also in HD. [AD,S]
// e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S]
2020-07-29 13:17:01 +02:00
if ( string . IsNullOrWhiteSpace ( subTitle )
& & ! string . IsNullOrWhiteSpace ( description )
2021-09-21 01:21:45 +02:00
& & description . AsSpan ( ) [ . . Math . Min ( description . Length , MaxSubtitleDescriptionExtractionLength ) ] . Contains ( ':' ) ) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
string [ ] descriptionParts = description . Split ( ':' ) ;
if ( descriptionParts . Length > 0 )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
string subtitle = descriptionParts [ 0 ] ;
2018-12-14 10:40:55 +01:00
try
{
2021-07-09 02:06:38 +02:00
// Check if it contains a episode number and season number
if ( subtitle . Contains ( '/' , StringComparison . Ordinal ) )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
string [ ] subtitleParts = subtitle . Split ( ' ' ) ;
string [ ] numbers = subtitleParts [ 0 ] . Replace ( "." , string . Empty , StringComparison . Ordinal ) . Split ( '/' ) ;
video . IndexNumber = int . Parse ( numbers [ 0 ] , CultureInfo . InvariantCulture ) ;
// int totalEpisodesInSeason = int.Parse(numbers[1], CultureInfo.InvariantCulture);
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
// Skip the numbers, concatenate the rest, trim and set as new description
description = string . Join ( ' ' , subtitleParts , 1 , subtitleParts . Length - 1 ) . Trim ( ) ;
}
else if ( subtitle . Contains ( '.' , StringComparison . Ordinal ) )
{
var subtitleParts = subtitle . Split ( '.' ) ;
description = string . Join ( '.' , subtitleParts , 1 , subtitleParts . Length - 1 ) . Trim ( ) ;
2018-12-14 10:40:55 +01:00
}
else
2020-06-20 11:19:16 +02:00
{
2021-07-09 02:06:38 +02:00
description = subtitle . Trim ( ) ;
2020-06-20 11:19:16 +02:00
}
2018-12-14 10:40:55 +01:00
}
2021-03-09 03:04:47 +01:00
catch ( Exception ex )
2018-12-14 10:40:55 +01:00
{
2021-03-09 03:04:47 +01:00
_logger . LogError ( ex , "Error while parsing subtitle field" ) ;
2021-07-09 02:06:38 +02:00
// Fallback to default parsing
2020-07-29 13:17:01 +02:00
if ( subtitle . Contains ( '.' , StringComparison . Ordinal ) )
{
2021-07-09 02:06:38 +02:00
var subtitleParts = subtitle . Split ( '.' ) ;
description = string . Join ( '.' , subtitleParts , 1 , subtitleParts . Length - 1 ) . Trim ( ) ;
2020-07-29 13:17:01 +02:00
}
2018-12-14 10:40:55 +01:00
else
2020-06-20 11:19:16 +02:00
{
2021-07-09 02:06:38 +02:00
description = subtitle . Trim ( ) ;
2020-06-20 11:19:16 +02:00
}
2018-12-14 10:40:55 +01:00
}
}
}
if ( ! string . IsNullOrWhiteSpace ( description ) )
{
video . Overview = description ;
}
}
private void ExtractTimestamp ( MediaInfo video )
{
2021-07-09 02:06:38 +02:00
if ( video . VideoType ! = VideoType . VideoFile )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
return ;
}
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
if ( ! string . Equals ( video . Container , "mpeg2ts" , StringComparison . OrdinalIgnoreCase )
& & ! string . Equals ( video . Container , "m2ts" , StringComparison . OrdinalIgnoreCase )
& & ! string . Equals ( video . Container , "ts" , StringComparison . OrdinalIgnoreCase ) )
{
return ;
}
try
{
video . Timestamp = GetMpegTimestamp ( video . Path ) ;
_logger . LogDebug ( "Video has {Timestamp} timestamp" , video . Timestamp ) ;
}
catch ( Exception ex )
{
video . Timestamp = null ;
_logger . LogError ( ex , "Error extracting timestamp info from {Path}" , video . Path ) ;
2018-12-14 10:40:55 +01:00
}
}
2020-01-06 10:39:01 +01:00
// REVIEW: find out why the byte array needs to be 197 bytes long and comment the reason
2018-12-14 10:40:55 +01:00
private TransportStreamTimestamp GetMpegTimestamp ( string path )
{
2020-01-02 20:19:01 +01:00
var packetBuffer = new byte [ 197 ] ;
2018-12-14 10:40:55 +01:00
2021-06-12 22:20:35 +02:00
using ( var fs = new FileStream ( path , FileMode . Open , FileAccess . Read , FileShare . Read , 1 ) )
2018-12-14 10:40:55 +01:00
{
2020-01-02 20:19:01 +01:00
fs . Read ( packetBuffer ) ;
2018-12-14 10:40:55 +01:00
}
if ( packetBuffer [ 0 ] = = 71 )
{
return TransportStreamTimestamp . None ;
}
2021-07-09 02:06:38 +02:00
if ( ( packetBuffer [ 4 ] ! = 71 ) | | ( packetBuffer [ 196 ] ! = 71 ) )
2018-12-14 10:40:55 +01:00
{
2021-07-09 02:06:38 +02:00
return TransportStreamTimestamp . None ;
}
2018-12-14 10:40:55 +01:00
2021-07-09 02:06:38 +02:00
if ( ( packetBuffer [ 0 ] = = 0 ) & & ( packetBuffer [ 1 ] = = 0 ) & & ( packetBuffer [ 2 ] = = 0 ) & & ( packetBuffer [ 3 ] = = 0 ) )
{
return TransportStreamTimestamp . Zero ;
2018-12-14 10:40:55 +01:00
}
2021-07-09 02:06:38 +02:00
return TransportStreamTimestamp . Valid ;
2018-12-14 10:40:55 +01:00
}
}
}