private async Task Sync(SyncJobItem jobItem, Video item, DeviceProfile profile, CancellationToken cancellationToken) { var options = new VideoOptions { Context = EncodingContext.Static, ItemId = item.Id.ToString("N"), DeviceId = jobItem.TargetId, Profile = profile, MediaSources = item.GetMediaSources(false).ToList() }; var streamInfo = new StreamBuilder().BuildVideoItem(options); var mediaSource = streamInfo.MediaSource; jobItem.MediaSourceId = streamInfo.MediaSourceId; if (streamInfo.PlayMethod == PlayMethod.Transcode) { jobItem.Status = SyncJobItemStatus.Converting; await _syncRepo.Update(jobItem).ConfigureAwait(false); jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, profile), new Progress<double>(), cancellationToken); } else { if (mediaSource.Protocol == MediaProtocol.File) { jobItem.OutputPath = mediaSource.Path; } else if (mediaSource.Protocol == MediaProtocol.Http) { jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false); } else { throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } } jobItem.Progress = 50; jobItem.Status = SyncJobItemStatus.Transferring; await _syncRepo.Update(jobItem).ConfigureAwait(false); }
private void AddVideoResource(XmlElement container, Video video, string deviceId, Filter filter, StreamInfo streamInfo = null) { if (streamInfo == null) { var sources = _user == null ? video.GetMediaSources(true).ToList() : video.GetMediaSources(true, _user).ToList(); streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions { ItemId = video.Id.ToString("N"), MediaSources = sources, Profile = _profile, DeviceId = deviceId, MaxBitrate = _profile.MaxStreamingBitrate }); } var targetWidth = streamInfo.TargetWidth; var targetHeight = streamInfo.TargetHeight; var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container, streamInfo.VideoCodec, streamInfo.AudioCodec, targetWidth, targetHeight, streamInfo.TargetVideoBitDepth, streamInfo.TargetVideoBitrate, streamInfo.TargetAudioChannels, streamInfo.TargetAudioBitrate, streamInfo.TargetTimestamp, streamInfo.IsDirectStream, streamInfo.RunTimeTicks, streamInfo.TargetVideoProfile, streamInfo.TargetVideoLevel, streamInfo.TargetFramerate, streamInfo.TargetPacketLength, streamInfo.TranscodeSeekInfo, streamInfo.IsTargetAnamorphic); foreach (var contentFeature in contentFeatureList) { AddVideoResource(container, video, deviceId, filter, contentFeature, streamInfo); } foreach (var subtitle in streamInfo.GetExternalSubtitles(_serverAddress)) { AddSubtitleElement(container, subtitle); } }
private async Task DownloadSubtitles(Video video, SubtitleOptions options, CancellationToken cancellationToken) { if ((options.DownloadEpisodeSubtitles && video is Episode) || (options.DownloadMovieSubtitles && video is Movie)) { var mediaStreams = video.GetMediaSources(false).First().MediaStreams; var downloadedLanguages = await new SubtitleDownloader(_logger, _subtitleManager) .DownloadSubtitles(video, mediaStreams, options.SkipIfGraphicalSubtitlesPresent, options.SkipIfAudioTrackMatches, options.DownloadLanguages, cancellationToken).ConfigureAwait(false); // Rescan if (downloadedLanguages.Count > 0) { await video.RefreshMetadata(cancellationToken).ConfigureAwait(false); } } }
private async Task DownloadSubtitles(Video video, CancellationToken cancellationToken) { if ((_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles && video is Episode) || (_config.Configuration.SubtitleOptions.DownloadMovieSubtitles && video is Movie)) { var mediaStreams = video.GetMediaSources(false).First().MediaStreams; var externalSubtitleStreams = mediaStreams.Where(i => i.Type == MediaStreamType.Subtitle && i.IsExternal).ToList(); var currentStreams = mediaStreams.Except(externalSubtitleStreams).ToList(); var downloadedLanguages = await new SubtitleDownloader(_logger, _subtitleManager) .DownloadSubtitles(video, currentStreams, externalSubtitleStreams, _config.Configuration.SubtitleOptions.SkipIfGraphicalSubtitlesPresent, _config.Configuration.SubtitleOptions.SkipIfAudioTrackMatches, _config.Configuration.SubtitleOptions.DownloadLanguages, cancellationToken).ConfigureAwait(false); // Rescan if (downloadedLanguages.Count > 0) { await video.RefreshMetadata(cancellationToken).ConfigureAwait(false); } } }
public async Task<DynamicImageResponse> GetVideoImage(Video item, CancellationToken cancellationToken) { var isoMount = await MountIsoIfNeeded(item, cancellationToken).ConfigureAwait(false); try { var protocol = item.LocationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File; var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, protocol, isoMount, item.PlayableStreamFileNames); var mediaStreams = item.GetMediaSources(false) .Take(1) .SelectMany(i => i.MediaStreams) .ToList(); var imageStreams = mediaStreams .Where(i => i.Type == MediaStreamType.EmbeddedImage) .ToList(); var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ?? imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ?? imageStreams.FirstOrDefault(); string extractedImagePath; if (imageStream != null) { // Instead of using the raw stream index, we need to use nth video/embedded image stream var videoIndex = -1; foreach (var mediaStream in mediaStreams) { if (mediaStream.Type == MediaStreamType.Video || mediaStream.Type == MediaStreamType.EmbeddedImage) { videoIndex++; } if (mediaStream == imageStream) { break; } } extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, videoIndex, cancellationToken).ConfigureAwait(false); } else { // If we know the duration, grab it from 10% into the video. Otherwise just 10 seconds in. // Always use 10 seconds for dvd because our duration could be out of whack var imageOffset = item.VideoType != VideoType.Dvd && item.RunTimeTicks.HasValue && item.RunTimeTicks.Value > 0 ? TimeSpan.FromTicks(Convert.ToInt64(item.RunTimeTicks.Value * .1)) : TimeSpan.FromSeconds(10); extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false); } return new DynamicImageResponse { Format = ImageFormat.Jpg, HasImage = true, Path = extractedImagePath, Protocol = MediaProtocol.File }; } finally { if (isoMount != null) { isoMount.Dispose(); } } }
private async Task<string> Sync(SyncJobItem jobItem, Video item, DeviceProfile profile, CancellationToken cancellationToken) { var options = new VideoOptions { Context = EncodingContext.Streaming, ItemId = item.Id.ToString("N"), DeviceId = jobItem.TargetId, Profile = profile, MediaSources = item.GetMediaSources(false).ToList() }; var streamInfo = new StreamBuilder().BuildVideoItem(options); var mediaSource = streamInfo.MediaSource; if (streamInfo.PlayMethod != PlayMethod.Transcode) { if (mediaSource.Protocol == MediaProtocol.File) { return mediaSource.Path; } if (mediaSource.Protocol == MediaProtocol.Http) { return await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false); } throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } // TODO: Transcode return mediaSource.Path; }