Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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));
        }
Beispiel #10
0
        /// <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));
        }
Beispiel #11
0
        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);
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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));
        }
Beispiel #14
0
        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);
        }
Beispiel #15
0
        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;
        }
Beispiel #16
0
        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;
                    }
                }
            }
        }
Beispiel #18
0
        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);
        }
Beispiel #19
0
        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;
        }