public async Task <MediaSourceInfo> GetLiveStreamMediaInfo(string id, CancellationToken cancellationToken) { // TODO probably shouldn't throw here but it is kept for "backwards compatibility" var liveStreamInfo = GetLiveStreamInfo(id) ?? throw new ResourceNotFoundException(); var mediaSource = liveStreamInfo.MediaSource; if (liveStreamInfo is IDirectStreamProvider) { var info = await _mediaEncoder.GetMediaInfo( new MediaInfoRequest { MediaSource = mediaSource, ExtractChapters = false, MediaType = DlnaProfileType.Video }, cancellationToken).ConfigureAwait(false); mediaSource.MediaStreams = info.MediaStreams; mediaSource.Container = info.Container; mediaSource.Bitrate = info.Bitrate; } return(mediaSource); }
public async Task <ItemUpdateType> Probe <T>(T item, MetadataRefreshOptions options, CancellationToken cancellationToken) where T : Audio { var path = item.Path; var protocol = item.PathProtocol ?? MediaProtocol.File; if (!item.IsShortcut || options.EnableRemoteContentProbe) { if (item.IsShortcut) { path = item.ShortcutPath; protocol = _mediaSourceManager.GetPathProtocol(path); } var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { MediaType = DlnaProfileType.Audio, MediaSource = new MediaSourceInfo { Path = path, Protocol = protocol } }, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); Fetch(item, cancellationToken, result); } return(ItemUpdateType.MetadataImport); }
private Task <Model.MediaInfo.MediaInfo> GetMediaInfo(Video item, string[] streamFileNames, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var path = item.Path; var protocol = item.PathProtocol ?? MediaProtocol.File; if (item.IsShortcut) { path = item.ShortcutPath; protocol = _mediaSourceManager.GetPathProtocol(path); } return(_mediaEncoder.GetMediaInfo(new MediaInfoRequest { PlayableStreamFileNames = streamFileNames, ExtractChapters = true, MediaType = DlnaProfileType.Video, MediaSource = new MediaSourceInfo { Path = path, Protocol = protocol, VideoType = item.VideoType } }, cancellationToken)); }
private async Task <Model.MediaInfo.MediaInfo> GetMediaInfo(BaseItem item, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); //var idString = item.Id.ToString("N"); //var cachePath = Path.Combine(_appPaths.CachePath, // "ffprobe-audio", // idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json"); //try //{ // return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath); //} //catch (FileNotFoundException) //{ //} //catch (DirectoryNotFoundException) //{ //} var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { InputPath = item.Path, MediaType = DlnaProfileType.Audio, Protocol = MediaProtocol.File }, cancellationToken).ConfigureAwait(false); //Directory.CreateDirectory(_fileSystem.GetDirectoryName(cachePath)); //_json.SerializeToFile(result, cachePath); return(result); }
private async Task <Model.MediaInfo.MediaInfo> GetMediaInfo(Video item, IIsoMount isoMount, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var protocol = item.LocationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File; var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { PlayableStreamFileNames = item.PlayableStreamFileNames, MountedIso = isoMount, ExtractChapters = true, VideoType = item.VideoType, MediaType = DlnaProfileType.Video, InputPath = item.Path, Protocol = protocol }, cancellationToken).ConfigureAwait(false); //Directory.CreateDirectory(Path.GetDirectoryName(cachePath)); //_json.SerializeToFile(result, cachePath); return(result); }
private async Task <InternalMediaInfoResult> GetMediaInfo(Video item, IIsoMount isoMount, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var idString = item.Id.ToString("N"); var cachePath = Path.Combine(_appPaths.CachePath, "ffprobe-video", idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json"); try { return(_json.DeserializeFromFile <InternalMediaInfoResult>(cachePath)); } catch (FileNotFoundException) { } catch (DirectoryNotFoundException) { } var protocol = item.LocationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File; var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, protocol, isoMount, item.PlayableStreamFileNames); var result = await _mediaEncoder.GetMediaInfo(inputPath, protocol, false, cancellationToken).ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(cachePath)); _json.SerializeToFile(result, cachePath); return(result); }
private async Task <InternalMediaInfoResult> GetMediaInfo(BaseItem item, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var idString = item.Id.ToString("N"); var cachePath = Path.Combine(_appPaths.CachePath, "ffprobe-audio", idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json"); try { return(_json.DeserializeFromFile <InternalMediaInfoResult>(cachePath)); } catch (FileNotFoundException) { } catch (DirectoryNotFoundException) { } var inputPath = new[] { item.Path }; var result = await _mediaEncoder.GetMediaInfo(inputPath, MediaProtocol.File, false, cancellationToken).ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(cachePath)); _json.SerializeToFile(result, cachePath); return(result); }
public async Task <MediaSourceInfo> GetLiveStreamMediaInfo(string id, CancellationToken cancellationToken) { var liveStreamInfo = await GetLiveStreamInfo(id, cancellationToken).ConfigureAwait(false); var mediaSource = liveStreamInfo.MediaSource; if (liveStreamInfo is IDirectStreamProvider) { var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { MediaSource = mediaSource, ExtractChapters = false, MediaType = DlnaProfileType.Video }, cancellationToken).ConfigureAwait(false); mediaSource.MediaStreams = info.MediaStreams; mediaSource.Container = info.Container; mediaSource.Bitrate = info.Bitrate; } return(mediaSource); }
/// <summary> /// Gets the media info. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{MediaInfoResult}.</returns> /// <exception cref="System.ArgumentNullException">inputPath /// or /// cache</exception> protected async Task <MediaInfoResult> GetMediaInfo(BaseItem item, IIsoMount isoMount, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var type = InputType.AudioFile; var inputPath = isoMount == null ? new[] { item.Path } : new[] { isoMount.MountedPath }; var video = item as Video; if (video != null) { inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type); } return(await MediaEncoder.GetMediaInfo(inputPath, type, cancellationToken).ConfigureAwait(false)); }
/// <summary> /// Returns the media info of the given audio file. /// </summary> /// <param name="path">The path to the audio file.</param> /// <param name="cancellationToken">The cancellation token to cancel operation.</param> /// <returns>The media info for the given audio file.</returns> private Task <Model.MediaInfo.MediaInfo> GetMediaInfo(string path, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return(_mediaEncoder.GetMediaInfo( new MediaInfoRequest { MediaType = DlnaProfileType.Audio, MediaSource = new MediaSourceInfo { Path = path, Protocol = MediaProtocol.File } }, cancellationToken)); }
public async Task <ItemUpdateType> Probe <T>(T item, CancellationToken cancellationToken) where T : Audio { var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { InputPath = item.Path, MediaType = DlnaProfileType.Audio, Protocol = MediaProtocol.File }, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); Fetch(item, cancellationToken, result); return(ItemUpdateType.MetadataImport); }
private async Task <Model.MediaInfo.MediaInfo> GetMediaInfo(Video item, IIsoMount isoMount, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var idString = item.Id.ToString("N"); var cachePath = Path.Combine(_appPaths.CachePath, "ffprobe-video", idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json"); try { return(_json.DeserializeFromFile <Model.MediaInfo.MediaInfo>(cachePath)); } catch (FileNotFoundException) { } catch (DirectoryNotFoundException) { } var protocol = item.LocationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File; var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { PlayableStreamFileNames = item.PlayableStreamFileNames, MountedIso = isoMount, ExtractChapters = true, VideoType = item.VideoType, MediaType = DlnaProfileType.Video, InputPath = item.Path, Protocol = protocol, ExtractKeyFrameInterval = true }, cancellationToken).ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(cachePath)); _json.SerializeToFile(result, cachePath); return(result); }
private Task <Model.MediaInfo.MediaInfo> GetMediaInfo(Video item, string[] streamFileNames, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var protocol = item.LocationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File; return(_mediaEncoder.GetMediaInfo(new MediaInfoRequest { PlayableStreamFileNames = streamFileNames, ExtractChapters = true, VideoType = item.VideoType, MediaType = DlnaProfileType.Video, InputPath = item.Path, Protocol = protocol }, cancellationToken)); }
private async Task <InternalMediaInfoResult> GetMediaInfo(BaseItem item, IIsoMount isoMount, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var idString = item.Id.ToString("N"); var cachePath = Path.Combine(_appPaths.CachePath, "ffprobe-video", idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json"); try { return(_json.DeserializeFromFile <InternalMediaInfoResult>(cachePath)); } catch (FileNotFoundException) { } catch (DirectoryNotFoundException) { } var type = InputType.File; var inputPath = isoMount == null ? new[] { item.Path } : new[] { isoMount.MountedPath }; var video = item as Video; if (video != null) { inputPath = MediaEncoderHelpers.GetInputArgument(video.Path, video.LocationType == LocationType.Remote, video.VideoType, video.IsoType, isoMount, video.PlayableStreamFileNames, out type); } var result = await _mediaEncoder.GetMediaInfo(inputPath, type, false, cancellationToken).ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(cachePath)); _json.SerializeToFile(result, cachePath); return(result); }
public async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) { var originalRuntime = mediaSource.RunTimeTicks; var now = DateTime.UtcNow; var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { InputPath = mediaSource.Path, Protocol = mediaSource.Protocol, MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, ExtractChapters = false, AnalyzeDurationMs = AnalyzeDurationMs }, cancellationToken).ConfigureAwait(false); _logger.Info("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture)); mediaSource.Bitrate = info.Bitrate; mediaSource.Container = info.Container; mediaSource.Formats = info.Formats; mediaSource.MediaStreams = info.MediaStreams; mediaSource.RunTimeTicks = info.RunTimeTicks; mediaSource.Size = info.Size; mediaSource.Timestamp = info.Timestamp; mediaSource.Video3DFormat = info.Video3DFormat; mediaSource.VideoType = info.VideoType; mediaSource.DefaultSubtitleStreamIndex = null; // Null this out so that it will be treated like a live stream if (!originalRuntime.HasValue) { mediaSource.RunTimeTicks = null; } var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Audio); if (audioStream == null || audioStream.Index == -1) { mediaSource.DefaultAudioStreamIndex = null; } else { mediaSource.DefaultAudioStreamIndex = audioStream.Index; } var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Video); if (videoStream != null) { if (!videoStream.BitRate.HasValue) { var width = videoStream.Width ?? 1920; if (width >= 3000) { videoStream.BitRate = 30000000; } else if (width >= 1900) { videoStream.BitRate = 20000000; } else if (width >= 1200) { videoStream.BitRate = 8000000; } else if (width >= 700) { videoStream.BitRate = 2000000; } } // This is coming up false and preventing stream copy videoStream.IsAVC = null; } // Try to estimate this mediaSource.InferTotalBitrate(true); mediaSource.AnalyzeDurationMs = AnalyzeDurationMs; }
private async Task ProbeStream(MediaSourceInfo mediaSourceInfo, string probeUrl, string source, CancellationToken cancellationToken) { _logger.Info("[TVHclient] Probe stream for {0}", source); _logger.Info("[TVHclient] Probe URL: {0}", probeUrl); MediaInfoRequest req = new MediaInfoRequest { MediaType = MediaBrowser.Model.Dlna.DlnaProfileType.Video, InputPath = probeUrl, Protocol = MediaProtocol.Http, ExtractChapters = false, VideoType = VideoType.VideoFile, // currently not available !!! // RequiredHttpHeaders = mediaSourceInfo.RequiredHttpHeaders, }; var originalRuntime = mediaSourceInfo.RunTimeTicks; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); MediaInfo info = await _mediaEncoder.GetMediaInfo(req, cancellationToken).ConfigureAwait(false); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); _logger.Info("[TVHclient] Probe RunTime " + elapsedTime); if (info != null) { _logger.Info("[TVHclient] Probe returned:"); mediaSourceInfo.Bitrate = info.Bitrate; _logger.Info("[TVHclient] BitRate: " + info.Bitrate); mediaSourceInfo.Container = info.Container; _logger.Info("[TVHclient] Container: " + info.Container); mediaSourceInfo.Formats = info.Formats; _logger.Info("[TVHclient] Formats: "); LogStringList(info.Formats, " "); mediaSourceInfo.MediaStreams = info.MediaStreams; _logger.Info("[TVHclient] MediaStreams: "); LogMediaStreamList(info.MediaStreams, " "); mediaSourceInfo.RunTimeTicks = info.RunTimeTicks; _logger.Info("[TVHclient] RunTimeTicks: " + info.RunTimeTicks); mediaSourceInfo.Size = info.Size; _logger.Info("[TVHclient] Size: " + info.Size); mediaSourceInfo.Timestamp = info.Timestamp; _logger.Info("[TVHclient] Timestamp: " + info.Timestamp); mediaSourceInfo.Video3DFormat = info.Video3DFormat; _logger.Info("[TVHclient] Video3DFormat: " + info.Video3DFormat); mediaSourceInfo.VideoType = info.VideoType; _logger.Info("[TVHclient] VideoType: " + info.VideoType); mediaSourceInfo.RequiresClosing = true; _logger.Info("[TVHclient] RequiresClosing: " + true); mediaSourceInfo.RequiresOpening = true; _logger.Info("[TVHclient] RequiresOpening: " + true); mediaSourceInfo.SupportsDirectPlay = true; _logger.Info("[TVHclient] SupportsDirectPlay: " + true); mediaSourceInfo.SupportsDirectStream = true; _logger.Info("[TVHclient] SupportsDirectStream: " + true); mediaSourceInfo.SupportsTranscoding = true; _logger.Info("[TVHclient] SupportsTranscoding: " + true); mediaSourceInfo.DefaultSubtitleStreamIndex = null; _logger.Info("[TVHclient] DefaultSubtitleStreamIndex: n/a"); if (!originalRuntime.HasValue) { mediaSourceInfo.RunTimeTicks = null; _logger.Info("[TVHclient] Original runtime: n/a"); } var audioStream = mediaSourceInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Audio); if (audioStream == null || audioStream.Index == -1) { mediaSourceInfo.DefaultAudioStreamIndex = null; _logger.Info("[TVHclient] DefaultAudioStreamIndex: n/a"); } else { mediaSourceInfo.DefaultAudioStreamIndex = audioStream.Index; _logger.Info("[TVHclient] DefaultAudioStreamIndex: '" + info.DefaultAudioStreamIndex + "'"); } } else { _logger.Error("[TVHclient] Cannot probe {0} stream", source); } }
private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) { var inputPaths = new[] { mediaSource.Path }; var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { InputPath = mediaSource.Path, Protocol = mediaSource.Protocol, MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, ExtractChapters = false }, cancellationToken) .ConfigureAwait(false); mediaSource.Bitrate = info.Bitrate; mediaSource.Container = info.Container; mediaSource.Formats = info.Formats; mediaSource.MediaStreams = info.MediaStreams; mediaSource.RunTimeTicks = info.RunTimeTicks; mediaSource.Size = info.Size; mediaSource.Timestamp = info.Timestamp; mediaSource.Video3DFormat = info.Video3DFormat; mediaSource.VideoType = info.VideoType; mediaSource.DefaultSubtitleStreamIndex = null; var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio); if (audioStream == null || audioStream.Index == -1) { mediaSource.DefaultAudioStreamIndex = null; } else { mediaSource.DefaultAudioStreamIndex = audioStream.Index; } // Try to estimate this if (!mediaSource.Bitrate.HasValue) { var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video); if (videoStream != null) { var width = videoStream.Width ?? 1920; if (width >= 1900) { mediaSource.Bitrate = 10000000; } else if (width >= 1260) { mediaSource.Bitrate = 6000000; } else if (width >= 700) { mediaSource.Bitrate = 4000000; } } } }
public async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, string cacheKey, bool addProbeDelay, CancellationToken cancellationToken) { var originalRuntime = mediaSource.RunTimeTicks; var now = DateTime.UtcNow; MediaInfo mediaInfo = null; var cacheFilePath = string.IsNullOrEmpty(cacheKey) ? null : Path.Combine(_appPaths.CachePath, "mediainfo", cacheKey.GetMD5().ToString("N", CultureInfo.InvariantCulture) + ".json"); if (!string.IsNullOrEmpty(cacheKey)) { try { await using FileStream jsonStream = File.OpenRead(cacheFilePath); mediaInfo = await JsonSerializer.DeserializeAsync <MediaInfo>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); // _logger.LogDebug("Found cached media info"); } catch { } } if (mediaInfo == null) { if (addProbeDelay) { var delayMs = mediaSource.AnalyzeDurationMs ?? 0; delayMs = Math.Max(3000, delayMs); if (delayMs > 0) { _logger.LogInformation("Waiting {0}ms before probing the live stream", delayMs); await Task.Delay(delayMs, cancellationToken).ConfigureAwait(false); } } mediaSource.AnalyzeDurationMs = 3000; mediaInfo = await _mediaEncoder.GetMediaInfo( new MediaInfoRequest { MediaSource = mediaSource, MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, ExtractChapters = false }, cancellationToken).ConfigureAwait(false); if (cacheFilePath != null) { Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); await using FileStream createStream = File.OpenWrite(cacheFilePath); await JsonSerializer.SerializeAsync(createStream, mediaInfo, _jsonOptions, cancellationToken).ConfigureAwait(false); // _logger.LogDebug("Saved media info to {0}", cacheFilePath); } } var mediaStreams = mediaInfo.MediaStreams; if (!string.IsNullOrEmpty(cacheKey)) { var newList = new List <MediaStream>(); newList.AddRange(mediaStreams.Where(i => i.Type == MediaStreamType.Video).Take(1)); newList.AddRange(mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Take(1)); foreach (var stream in newList) { stream.Index = -1; stream.Language = null; } mediaStreams = newList; } _logger.LogInformation("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture)); mediaSource.Bitrate = mediaInfo.Bitrate; mediaSource.Container = mediaInfo.Container; mediaSource.Formats = mediaInfo.Formats; mediaSource.MediaStreams = mediaStreams; mediaSource.RunTimeTicks = mediaInfo.RunTimeTicks; mediaSource.Size = mediaInfo.Size; mediaSource.Timestamp = mediaInfo.Timestamp; mediaSource.Video3DFormat = mediaInfo.Video3DFormat; mediaSource.VideoType = mediaInfo.VideoType; mediaSource.DefaultSubtitleStreamIndex = null; // Null this out so that it will be treated like a live stream if (!originalRuntime.HasValue) { mediaSource.RunTimeTicks = null; } var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); if (audioStream == null || audioStream.Index == -1) { mediaSource.DefaultAudioStreamIndex = null; } else { mediaSource.DefaultAudioStreamIndex = audioStream.Index; } var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); if (videoStream != null) { if (!videoStream.BitRate.HasValue) { var width = videoStream.Width ?? 1920; if (width >= 3000) { videoStream.BitRate = 30000000; } else if (width >= 1900) { videoStream.BitRate = 20000000; } else if (width >= 1200) { videoStream.BitRate = 8000000; } else if (width >= 700) { videoStream.BitRate = 2000000; } } // This is coming up false and preventing stream copy videoStream.IsAVC = null; } mediaSource.AnalyzeDurationMs = 3000; // Try to estimate this mediaSource.InferTotalBitrate(true); }
public async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, string cacheKey, CancellationToken cancellationToken) { var originalRuntime = mediaSource.RunTimeTicks; var now = DateTime.UtcNow; MediaInfo mediaInfo = null; var cacheFilePath = string.IsNullOrWhiteSpace(cacheKey) ? null : Path.Combine(_appPaths.CachePath, "livetvmediainfo", cacheKey.GetMD5().ToString("N") + ".json"); if (!string.IsNullOrWhiteSpace(cacheKey)) { try { mediaInfo = _json.DeserializeFromFile <MediaInfo>(cacheFilePath); //_logger.Debug("Found cached media info"); } catch (Exception ex) { } } if (mediaInfo == null) { var path = mediaSource.Path; var protocol = mediaSource.Protocol; if (!string.IsNullOrWhiteSpace(mediaSource.EncoderPath) && mediaSource.EncoderProtocol.HasValue) { path = mediaSource.EncoderPath; protocol = mediaSource.EncoderProtocol.Value; } mediaInfo = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { InputPath = path, Protocol = protocol, MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, ExtractChapters = false, AnalyzeDurationMs = ProbeAnalyzeDurationMs }, cancellationToken).ConfigureAwait(false); if (cacheFilePath != null) { Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); _json.SerializeToFile(mediaInfo, cacheFilePath); //_logger.Debug("Saved media info to {0}", cacheFilePath); } } var mediaStreams = mediaInfo.MediaStreams; if (!string.IsNullOrWhiteSpace(cacheKey)) { var newList = new List <MediaStream>(); newList.AddRange(mediaStreams.Where(i => i.Type == MediaStreamType.Video).Take(1)); newList.AddRange(mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Take(1)); foreach (var stream in newList) { stream.Index = -1; stream.Language = null; } mediaStreams = newList; } _logger.Info("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture)); mediaSource.Bitrate = mediaInfo.Bitrate; mediaSource.Container = mediaInfo.Container; mediaSource.Formats = mediaInfo.Formats; mediaSource.MediaStreams = mediaStreams; mediaSource.RunTimeTicks = mediaInfo.RunTimeTicks; mediaSource.Size = mediaInfo.Size; mediaSource.Timestamp = mediaInfo.Timestamp; mediaSource.Video3DFormat = mediaInfo.Video3DFormat; mediaSource.VideoType = mediaInfo.VideoType; mediaSource.DefaultSubtitleStreamIndex = null; // Null this out so that it will be treated like a live stream if (!originalRuntime.HasValue) { mediaSource.RunTimeTicks = null; } var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Audio); if (audioStream == null || audioStream.Index == -1) { mediaSource.DefaultAudioStreamIndex = null; } else { mediaSource.DefaultAudioStreamIndex = audioStream.Index; } var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Video); if (videoStream != null) { if (!videoStream.BitRate.HasValue) { var width = videoStream.Width ?? 1920; if (width >= 3000) { videoStream.BitRate = 30000000; } else if (width >= 1900) { videoStream.BitRate = 20000000; } else if (width >= 1200) { videoStream.BitRate = 8000000; } else if (width >= 700) { videoStream.BitRate = 2000000; } } // This is coming up false and preventing stream copy videoStream.IsAVC = null; } // Try to estimate this mediaSource.InferTotalBitrate(true); mediaSource.AnalyzeDurationMs = PlaybackAnalyzeDurationMs; }