/// <summary> /// Finds vob files and populates the dvd stream file properties /// </summary> /// <param name="video">The video.</param> /// <param name="isoMount">The iso mount.</param> private void PopulateDvdStreamFiles(Video video, IIsoMount isoMount) { // min size 300 mb const long minPlayableSize = 314572800; var root = isoMount != null ? isoMount.MountedPath : video.Path; // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size // Once we reach a file that is at least the minimum, return all subsequent ones var files = Directory.EnumerateFiles(root, "*.vob", SearchOption.AllDirectories).SkipWhile(f => new FileInfo(f).Length < minPlayableSize).ToList(); // Assuming they're named "vts_05_01", take all files whose second part matches that of the first file if (files.Count > 0) { var parts = Path.GetFileNameWithoutExtension(files[0]).Split('_'); if (parts.Length == 3) { var title = parts[1]; files = files.TakeWhile(f => { var fileParts = Path.GetFileNameWithoutExtension(f).Split('_'); return(fileParts.Length == 3 && string.Equals(title, fileParts[1], StringComparison.OrdinalIgnoreCase)); }).ToList(); } } video.PlayableStreamFileNames = files.Select(Path.GetFileName).ToList(); }
private async Task <PlayableItem> GetPlayableItem(BaseItemDto item, long?startTimeTicks, CancellationToken cancellationToken) { IIsoMount mountedIso = null; if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Iso && item.IsoType.HasValue && _isoManager.CanMount(item.Path)) { try { mountedIso = await _isoManager.Mount(item.Path, cancellationToken); } catch (Exception ex) { _logger.ErrorException("Error mounting iso {0}", ex, item.Path); } } var apiClient = _connectionManager.GetApiClient(item); var mediaSources = item.MediaSources; try { var result = await apiClient.GetLiveMediaInfo(item.Id, apiClient.CurrentUserId); mediaSources = result.MediaSources; } catch { } return(PlayablePathBuilder.GetPlayableItem(item, mediaSources, mountedIso, apiClient, startTimeTicks, _config.Configuration.MaxStreamingBitrate)); }
async void process_Exited(object sender, EventArgs e) { var process = (Process)sender; if (_isoMount != null) { _isoMount.Dispose(); _isoMount = null; } DisposeLogFileStream(); try { _logger.Info("FFMpeg exited with code {0} for {1}", process.ExitCode, _task.Request.OutputPath); } catch { _logger.Info("FFMpeg exited with an error for {0}", _task.Request.OutputPath); } _task.OnCompleted(); if (!string.IsNullOrEmpty(_task.LiveTvStreamId)) { try { await _liveTvManager.CloseLiveStream(_task.LiveTvStreamId, CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) { _logger.ErrorException("Error closing live tv stream", ex); } } }
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); }
/// <summary> /// Gets the playable path. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="apiClient">The API client.</param> /// <param name="startTimeTicks">The start time ticks.</param> /// <returns>System.String.</returns> public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient, long? startTimeTicks) { // Check the mounted path first if (isoMount != null) { if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay) { return GetBlurayPath(isoMount.MountedPath); } return isoMount.MountedPath; } // Stream remote items through the api if (item.LocationType == LocationType.Remote) { return GetStreamedPath(item, apiClient, startTimeTicks); } // Stream if we can't access the file system if (!File.Exists(item.Path) && !Directory.Exists(item.Path)) { return GetStreamedPath(item, apiClient, startTimeTicks); } if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay) { return GetBlurayPath(item.Path); } return item.Path; }
/// <summary> /// Gets the playable path. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="apiClient">The API client.</param> /// <param name="startTimeTicks">The start time ticks.</param> /// <returns>System.String.</returns> public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient, long? startTimeTicks, int? maxBitrate) { // Check the mounted path first if (isoMount != null) { if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay) { return GetBlurayPath(isoMount.MountedPath); } return isoMount.MountedPath; } if (item.LocationType == LocationType.FileSystem) { if (File.Exists(item.Path) || Directory.Exists(item.Path)) { if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay) { return GetBlurayPath(item.Path); } return item.Path; } } return GetStreamedPath(item, apiClient, startTimeTicks, maxBitrate); }
/// <summary> /// Finds vob files and populates the dvd stream file properties /// </summary> /// <param name="video">The video.</param> /// <param name="isoMount">The iso mount.</param> private void PopulateDvdStreamFiles(Video video, IIsoMount isoMount) { // min size 300 mb const long minPlayableSize = 314572800; var root = isoMount != null ? isoMount.MountedPath : video.Path; // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size // Once we reach a file that is at least the minimum, return all subsequent ones video.PlayableStreamFileNames = Directory.EnumerateFiles(root, "*.vob", SearchOption.AllDirectories).SkipWhile(f => new FileInfo(f).Length < minPlayableSize).Select(Path.GetFileName).ToList(); }
/// <summary> /// Gets the input argument. /// </summary> /// <param name="fileSystem">The file system.</param> /// <param name="videoPath">The video path.</param> /// <param name="protocol">The protocol.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="playableStreamFileNames">The playable stream file names.</param> /// <returns>System.String[][].</returns> public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, MediaProtocol protocol, IIsoMount isoMount, List<string> playableStreamFileNames) { if (playableStreamFileNames.Count > 0) { if (isoMount == null) { return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames).ToArray(); } return GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames).ToArray(); } return new[] {videoPath}; }
/// <summary> /// Called when [pre fetch]. /// </summary> /// <param name="item">The item.</param> /// <param name="mount">The mount.</param> protected override void OnPreFetch(Video item, IIsoMount mount) { if (item.VideoType == VideoType.Iso) { item.IsoType = DetermineIsoType(mount); } if (item.VideoType == VideoType.Dvd || (item.IsoType.HasValue && item.IsoType == IsoType.Dvd)) { PopulateDvdStreamFiles(item, mount); } base.OnPreFetch(item, mount); }
/// <summary> /// Determines the type of the iso. /// </summary> /// <param name="isoMount">The iso mount.</param> /// <returns>System.Nullable{IsoType}.</returns> private IsoType?DetermineIsoType(IIsoMount isoMount) { var folders = Directory.EnumerateDirectories(isoMount.MountedPath).Select(Path.GetFileName).ToList(); if (folders.Contains("video_ts", StringComparer.OrdinalIgnoreCase)) { return(IsoType.Dvd); } if (folders.Contains("bdmv", StringComparer.OrdinalIgnoreCase)) { return(IsoType.BluRay); } return(null); }
/// <summary> /// Gets the input argument. /// </summary> /// <param name="item">The item.</param> /// <param name="mount">The mount.</param> /// <returns>System.String.</returns> public string GetInputArgument(Video item, IIsoMount mount) { if (item.VideoType == VideoType.Iso && item.IsoType.HasValue) { if (item.IsoType.Value == IsoType.BluRay) { return(GetBlurayInputArgument(mount.MountedPath)); } if (item.IsoType.Value == IsoType.Dvd) { return(GetDvdInputArgument(item.GetPlayableStreamFiles(mount.MountedPath))); } } return(GetInputArgument(item)); }
/// <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> /// Determines the type of the iso. /// </summary> /// <param name="isoMount">The iso mount.</param> /// <returns>System.Nullable{IsoType}.</returns> private IsoType?DetermineIsoType(IIsoMount isoMount) { var fileSystemEntries = _fileSystem.GetFileSystemEntryPaths(isoMount.MountedPath).Select(Path.GetFileName).ToList(); if (fileSystemEntries.Contains("video_ts", StringComparer.OrdinalIgnoreCase) || fileSystemEntries.Contains("VIDEO_TS.IFO", StringComparer.OrdinalIgnoreCase)) { return(IsoType.Dvd); } if (fileSystemEntries.Contains("bdmv", StringComparer.OrdinalIgnoreCase)) { return(IsoType.BluRay); } return(null); }
/// <summary> /// Gets the input argument. /// </summary> /// <param name="video">The video.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="type">The type.</param> /// <returns>System.String[][].</returns> public static string[] GetInputArgument(Video video, IIsoMount isoMount, out InputType type) { var inputPath = isoMount == null ? new[] { video.Path } : new[] { isoMount.MountedPath }; type = InputType.VideoFile; switch (video.VideoType) { case VideoType.BluRay: type = InputType.Bluray; break; case VideoType.Dvd: type = InputType.Dvd; inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray(); break; case VideoType.Iso: if (video.IsoType.HasValue) { switch (video.IsoType.Value) { case IsoType.BluRay: type = InputType.Bluray; break; case IsoType.Dvd: type = InputType.Dvd; inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray(); break; } } break; case VideoType.VideoFile: { if (video.LocationType == LocationType.Remote) { type = InputType.Url; } break; } } return(inputPath); }
/// <summary> /// Called when [pre fetch]. /// </summary> /// <param name="item">The item.</param> /// <param name="mount">The mount.</param> /// <param name="blurayDiscInfo">The bluray disc information.</param> private void OnPreFetch(Video item, IIsoMount mount, BlurayDiscInfo blurayDiscInfo) { if (item.VideoType == VideoType.Iso) { item.IsoType = DetermineIsoType(mount); } if (item.VideoType == VideoType.Dvd || (item.IsoType.HasValue && item.IsoType == IsoType.Dvd)) { FetchFromDvdLib(item, mount); } if (item.VideoType == VideoType.BluRay || (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay)) { item.PlayableStreamFileNames = blurayDiscInfo.Files.ToList(); } }
/// <summary> /// Gets the input argument. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>System.String.</returns> protected string GetInputArgument(BaseItem item, IIsoMount isoMount) { var type = InputType.AudioFile; var inputPath = new[] { item.Path }; var video = item as Video; if (video != null) { if (!(video.VideoType == VideoType.Iso && isoMount == null)) { inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type); } } return(MediaEncoder.GetInputArgument(inputPath, type)); }
private async Task <IIsoMount> GetIsoMount(BaseItemDto item, CancellationToken cancellationToken) { IIsoMount mountedIso = null; if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Iso && item.IsoType.HasValue && _isoManager.CanMount(item.Path)) { try { mountedIso = await _isoManager.Mount(item.Path, cancellationToken); } catch (Exception ex) { Logger.ErrorException("Error mounting iso {0}", ex, item.Path); } } return(mountedIso); }
/// <summary> /// Gets the input argument. /// </summary> /// <param name="videoPath">The video path.</param> /// <param name="isRemote">if set to <c>true</c> [is remote].</param> /// <param name="videoType">Type of the video.</param> /// <param name="isoType">Type of the iso.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="playableStreamFileNames">The playable stream file names.</param> /// <param name="type">The type.</param> /// <returns>System.String[][].</returns> public static string[] GetInputArgument(string videoPath, bool isRemote, VideoType videoType, IsoType? isoType, IIsoMount isoMount, IEnumerable<string> playableStreamFileNames, out InputType type) { var inputPath = isoMount == null ? new[] { videoPath } : new[] { isoMount.MountedPath }; type = InputType.File; switch (videoType) { case VideoType.BluRay: type = InputType.Bluray; inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray(); break; case VideoType.Dvd: type = InputType.Dvd; inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray(); break; case VideoType.Iso: if (isoType.HasValue) { switch (isoType.Value) { case IsoType.BluRay: type = InputType.Bluray; inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray(); break; case IsoType.Dvd: type = InputType.Dvd; inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray(); break; } } break; case VideoType.VideoFile: { if (isRemote) { type = InputType.Url; } break; } } return inputPath; }
private void FetchFromDvdLib(Video item, IIsoMount mount) { var path = mount == null ? item.Path : mount.MountedPath; var dvd = new Dvd(path); var primaryTitle = dvd.Titles.OrderByDescending(GetRuntime).FirstOrDefault(); byte?titleNumber = null; if (primaryTitle != null) { titleNumber = primaryTitle.VideoTitleSetNumber; item.RunTimeTicks = GetRuntime(primaryTitle); } item.PlayableStreamFileNames = GetPrimaryPlaylistVobFiles(item, mount, titleNumber) .Select(Path.GetFileName) .ToList(); }
private string[] FetchFromDvdLib(Video item, IIsoMount mount) { var path = mount == null ? item.Path : mount.MountedPath; var dvd = new Dvd(path, _fileSystem); var primaryTitle = dvd.Titles.OrderByDescending(GetRuntime).FirstOrDefault(); byte?titleNumber = null; if (primaryTitle != null) { titleNumber = primaryTitle.VideoTitleSetNumber; item.RunTimeTicks = GetRuntime(primaryTitle); } return(_mediaEncoder.GetPrimaryPlaylistVobFiles(item.Path, mount, titleNumber) .Select(Path.GetFileName) .ToArray()); }
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); }
/// <summary> /// Plays the specified options. /// </summary> /// <param name="options">The options.</param> /// <returns>Task.</returns> public async Task Play(PlayOptions options) { _currentIsoMount = options.Items.Count == 1 && options.Configuration.IsoMethod == IsoConfiguration.Mount ? await GetIsoMount(options.Items[0], CancellationToken.None) : null; CurrentPlaylistIndex = 0; CurrentPlayOptions = options; _playlist = options.Items.ToList(); var process = new Process { EnableRaisingEvents = true, StartInfo = GetProcessStartInfo(options.Items, options, _currentIsoMount) }; Logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); try { process.Start(); } catch (Exception ex) { Logger.ErrorException("Error starting player", ex); _playlist.Clear(); throw; } if (options.Configuration.CloseOnStopButton && !CanCloseAutomaticallyOnStopButton) { _userInput.GlobalKeyDown += KeyboardListener_KeyDown; } process.Exited += CurrentProcess_Exited; _currentProcess = process; OnPlayerLaunched(); }
/// <summary> /// Gets the input argument. /// </summary> /// <param name="video">The video.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="type">The type.</param> /// <returns>System.String[][].</returns> public static string[] GetInputArgument(Video video, IIsoMount isoMount, out InputType type) { var inputPath = isoMount == null ? new[] { video.Path } : new[] { isoMount.MountedPath }; type = InputType.VideoFile; switch (video.VideoType) { case VideoType.BluRay: type = InputType.Bluray; break; case VideoType.Dvd: type = InputType.Dvd; inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray(); break; case VideoType.Iso: if (video.IsoType.HasValue) { switch (video.IsoType.Value) { case IsoType.BluRay: type = InputType.Bluray; break; case IsoType.Dvd: type = InputType.Dvd; inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray(); break; } } break; case VideoType.VideoFile: { if (video.LocationType == LocationType.Remote) { type = InputType.Url; } break; } } return inputPath; }
/// <summary> /// Gets the playable path. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="apiClient">The API client.</param> /// <returns>System.String.</returns> public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient) { // Check the mounted path first if (isoMount != null) { if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay) { return GetBlurayPath(isoMount.MountedPath); } return isoMount.MountedPath; } // Stream remote items through the api if (item.LocationType == LocationType.Remote) { return apiClient.GetVideoStreamUrl(new VideoStreamOptions { ItemId = item.Id, Static = true }); } // Stream if we can't access the file system if (!File.Exists(item.Path) && !Directory.Exists(item.Path)) { return apiClient.GetVideoStreamUrl(new VideoStreamOptions { Static = true, ItemId = item.Id }); } if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay) { return GetBlurayPath(item.Path); } return item.Path; }
/// <summary> /// Gets the playable path. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="apiClient">The API client.</param> /// <returns>System.String.</returns> public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient) { // Check the mounted path first if (isoMount != null) { if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay) { return(GetBlurayPath(isoMount.MountedPath)); } return(isoMount.MountedPath); } // Stream remote items through the api if (item.LocationType == LocationType.Remote) { return(apiClient.GetVideoStreamUrl(new VideoStreamOptions { ItemId = item.Id, Static = true })); } // Stream if we can't access the file system if (!File.Exists(item.Path) && !Directory.Exists(item.Path)) { return(apiClient.GetVideoStreamUrl(new VideoStreamOptions { Static = true, ItemId = item.Id })); } if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay) { return(GetBlurayPath(item.Path)); } return(item.Path); }
private async Task <PlayableItem> GetPlayableItem(BaseItemDto item, CancellationToken cancellationToken) { IIsoMount mountedIso = null; if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Iso && item.IsoType.HasValue && _isoManager.CanMount(item.Path)) { try { mountedIso = await _isoManager.Mount(item.Path, cancellationToken); } catch (Exception ex) { _logger.ErrorException("Error mounting iso {0}", ex, item.Path); } } return(new PlayableItem { OriginalItem = item, PlayablePath = PlayablePathBuilder.GetPlayablePath(item, mountedIso, _apiClient) }); }
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); }
private Task <Model.MediaInfo.MediaInfo> GetMediaInfo(Video item, IIsoMount isoMount, List <string> streamFileNames, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var protocol = item.LocationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File; return(_mediaEncoder.GetMediaInfo(new MediaInfoRequest { PlayableStreamFileNames = streamFileNames, MountedIso = isoMount, ExtractChapters = true, VideoType = item.VideoType, MediaType = DlnaProfileType.Video, InputPath = item.Path, Protocol = protocol }, cancellationToken)); }
/// <summary> /// Gets the playable path. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="apiClient">The API client.</param> /// <param name="startTimeTicks">The start time ticks.</param> /// <returns>System.String.</returns> public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient, long?startTimeTicks, int?maxBitrate) { // Check the mounted path first if (isoMount != null) { if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay) { return(GetBlurayPath(isoMount.MountedPath)); } return(isoMount.MountedPath); } if (item.LocationType == LocationType.FileSystem) { if (File.Exists(item.Path) || Directory.Exists(item.Path)) { if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay) { return(GetBlurayPath(item.Path)); } if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Dvd) { return(item.Path); } if (item.VideoType.HasValue && item.VideoType.Value == VideoType.HdDvd) { return(item.Path); } //return item.Path; } } return(GetStreamedPath(item, apiClient, startTimeTicks, maxBitrate)); }
/// <summary> /// Handles the Exited event of the CurrentProcess control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> void CurrentProcess_Exited(object sender, EventArgs e) { _currentProcess = null; _userInput.GlobalKeyDown -= KeyboardListener_KeyDown; var process = (Process)sender; var playlist = _playlist.ToList(); var index = CurrentPlaylistIndex; var ticks = CurrentPositionTicks; process.Dispose(); if (_currentIsoMount != null) { _currentIsoMount.Dispose(); _currentIsoMount = null; } var media = index != -1 && playlist.Count > 0 ? playlist[index] : null; var args = new PlaybackStopEventArgs { Playlist = playlist, Player = this, EndingPlaylistIndex = index, EndingPositionTicks = ticks, EndingMedia = media }; EventHelper.QueueEventIfNotNull(PlaybackCompleted, this, args, Logger); _playbackManager.ReportPlaybackCompleted(args); OnPlayerExited(); }
protected async Task Fetch(Video video, CancellationToken cancellationToken, InternalMediaInfoResult data, IIsoMount isoMount, BlurayDiscInfo blurayInfo, MetadataRefreshOptions options) { var mediaInfo = MediaEncoderHelpers.GetMediaInfo(data); var mediaStreams = mediaInfo.MediaStreams; video.TotalBitrate = mediaInfo.TotalBitrate; video.FormatName = (mediaInfo.Format ?? string.Empty) .Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase); if (data.format != null) { // For dvd's this may not always be accurate, so don't set the runtime if the item already has one var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0; if (needToSetRuntime && !string.IsNullOrEmpty(data.format.duration)) { video.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, _usCulture)).Ticks; } if (video.VideoType == VideoType.VideoFile) { var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.'); video.Container = extension; } else { video.Container = null; } if (!string.IsNullOrEmpty(data.format.size)) { video.Size = long.Parse(data.format.size, _usCulture); } else { video.Size = null; } } var mediaChapters = (data.Chapters ?? new MediaChapter[] { }).ToList(); var chapters = mediaChapters.Select(GetChapterInfo).ToList(); if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay)) { FetchBdInfo(video, chapters, mediaStreams, blurayInfo); } await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false); FetchWtvInfo(video, data); video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270); var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); video.VideoBitRate = videoStream == null ? null : videoStream.BitRate; video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index; video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle); ExtractTimestamp(video); UpdateFromMediaInfo(video, videoStream); await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false); if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || options.MetadataRefreshMode == MetadataRefreshMode.Default) { var chapterOptions = _chapterManager.GetConfiguration(); try { var remoteChapters = await DownloadChapters(video, chapters, chapterOptions, cancellationToken).ConfigureAwait(false); if (remoteChapters.Count > 0) { chapters = remoteChapters; } } catch (Exception ex) { _logger.ErrorException("Error downloading chapters", ex); } if (chapters.Count == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video)) { AddDummyChapters(video, chapters); } NormalizeChapterNames(chapters); await _encodingManager.RefreshChapterImages(new ChapterImageRefreshOptions { Chapters = chapters, Video = video, ExtractImages = chapterOptions.ExtractDuringLibraryScan, SaveChapters = false }, cancellationToken).ConfigureAwait(false); await _chapterManager.SaveChapters(video.Id.ToString(), chapters, cancellationToken).ConfigureAwait(false); } }
/// <summary> /// Gets the process start info. /// </summary> /// <param name="items">The items.</param> /// <param name="options">The options.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>ProcessStartInfo.</returns> protected virtual ProcessStartInfo GetProcessStartInfo(IEnumerable<BaseItemDto> items, PlayOptions options, IIsoMount isoMount) { return new ProcessStartInfo { FileName = options.Configuration.Command, Arguments = GetCommandArguments(items, options, isoMount) }; }
/// <summary> /// Gets the command arguments. /// </summary> /// <param name="items">The items.</param> /// <param name="options">The options.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>System.String.</returns> protected virtual string GetCommandArguments(IEnumerable<BaseItemDto> items, PlayOptions options, IIsoMount isoMount) { return GetCommandArguments(items, options.Configuration.Args, isoMount); }
protected async Task Fetch(Video video, CancellationToken cancellationToken, Model.MediaInfo.MediaInfo mediaInfo, IIsoMount isoMount, BlurayDiscInfo blurayInfo, MetadataRefreshOptions options) { var mediaStreams = mediaInfo.MediaStreams; video.TotalBitrate = mediaInfo.Bitrate; //video.FormatName = (mediaInfo.Container ?? string.Empty) // .Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase); // For dvd's this may not always be accurate, so don't set the runtime if the item already has one var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0; if (needToSetRuntime) { video.RunTimeTicks = mediaInfo.RunTimeTicks; } if (video.VideoType == VideoType.VideoFile) { var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.'); video.Container = extension; } else { video.Container = null; } var chapters = mediaInfo.Chapters ?? new List <ChapterInfo>(); if (blurayInfo != null) { FetchBdInfo(video, chapters, mediaStreams, blurayInfo); } await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false); var libraryOptions = _libraryManager.GetLibraryOptions(video); FetchEmbeddedInfo(video, mediaInfo, options, libraryOptions); await FetchPeople(video, mediaInfo, options).ConfigureAwait(false); video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1260); var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index; video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle); video.Timestamp = mediaInfo.Timestamp; video.Video3DFormat = video.Video3DFormat ?? mediaInfo.Video3DFormat; await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false); if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || options.MetadataRefreshMode == MetadataRefreshMode.Default) { if (chapters.Count == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video)) { AddDummyChapters(video, chapters); } NormalizeChapterNames(chapters); var extractDuringScan = false; if (libraryOptions != null) { extractDuringScan = libraryOptions.ExtractChapterImagesDuringLibraryScan; } await _encodingManager.RefreshChapterImages(new ChapterImageRefreshOptions { Chapters = chapters, Video = video, ExtractImages = extractDuringScan, SaveChapters = false }, cancellationToken).ConfigureAwait(false); await _chapterManager.SaveChapters(video.Id.ToString(), chapters, cancellationToken).ConfigureAwait(false); } }
public IEnumerable <string> GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint?titleNumber) { throw new NotImplementedException(); }
/// <summary> /// Gets the input argument. /// </summary> /// <param name="fileSystem">The file system.</param> /// <param name="videoPath">The video path.</param> /// <param name="protocol">The protocol.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="playableStreamFileNames">The playable stream file names.</param> /// <returns>System.String[][].</returns> public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, MediaProtocol protocol, IIsoMount isoMount, string[] playableStreamFileNames) { if (playableStreamFileNames.Length > 0) { if (isoMount == null) { return(GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames)); } return(GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames)); } return(new[] { videoPath }); }
/// <summary> /// Gets the path for command line. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>System.String.</returns> protected virtual string GetPathForCommandLine(BaseItemDto item, IIsoMount isoMount) { return isoMount == null ? item.Path : isoMount.MountedPath; }
public async Task Start(InternalEncodingTask task, Func<InternalEncodingTask,string,string> argumentsFactory) { _task = task; if (!File.Exists(_ffmpegPath)) { throw new InvalidOperationException("ffmpeg was not found at " + _ffmpegPath); } Directory.CreateDirectory(Path.GetDirectoryName(task.Request.OutputPath)); string mountedPath = null; if (task.InputVideoType.HasValue && task.InputVideoType == VideoType.Iso && task.IsoType.HasValue) { if (_isoManager.CanMount(task.MediaPath)) { _isoMount = await _isoManager.Mount(task.MediaPath, CancellationToken.None).ConfigureAwait(false); mountedPath = _isoMount.MountedPath; } } var process = new Process { StartInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, // Must consume both stdout and stderr or deadlocks may occur RedirectStandardOutput = true, RedirectStandardError = true, FileName = _ffmpegPath, WorkingDirectory = Path.GetDirectoryName(_ffmpegPath), Arguments = argumentsFactory(task, mountedPath), WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }, EnableRaisingEvents = true }; _logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-" + task.Id + ".txt"); Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. _logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); process.Exited += process_Exited; try { process.Start(); } catch (Exception ex) { _logger.ErrorException("Error starting ffmpeg", ex); task.OnError(); DisposeLogFileStream(); process.Dispose(); throw; } task.OnBegin(); // MUST read both stdout and stderr asynchronously or a deadlock may occurr process.BeginOutputReadLine(); #pragma warning disable 4014 // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback process.StandardError.BaseStream.CopyToAsync(_logFileStream); #pragma warning restore 4014 }
private IEnumerable <string> GetPrimaryPlaylistVobFiles(Video video, IIsoMount isoMount, uint?titleNumber) { // min size 300 mb const long minPlayableSize = 314572800; var root = isoMount != null ? isoMount.MountedPath : video.Path; // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size // Once we reach a file that is at least the minimum, return all subsequent ones var allVobs = new DirectoryInfo(root).EnumerateFiles("*", SearchOption.AllDirectories) .Where(file => string.Equals(file.Extension, ".vob", StringComparison.OrdinalIgnoreCase)) .OrderBy(i => i.FullName) .ToList(); // If we didn't find any satisfying the min length, just take them all if (allVobs.Count == 0) { _logger.Error("No vobs found in dvd structure."); return(new List <string>()); } if (titleNumber.HasValue) { var prefix = string.Format("VTS_0{0}_", titleNumber.Value.ToString(_usCulture)); var vobs = allVobs.Where(i => i.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)).ToList(); if (vobs.Count > 0) { var minSizeVobs = vobs .SkipWhile(f => f.Length < minPlayableSize) .ToList(); return(minSizeVobs.Count == 0 ? vobs.Select(i => i.FullName) : minSizeVobs.Select(i => i.FullName)); } _logger.Debug("Could not determine vob file list for {0} using DvdLib. Will scan using file sizes.", video.Path); } var files = allVobs .SkipWhile(f => f.Length < minPlayableSize) .ToList(); // If we didn't find any satisfying the min length, just take them all if (files.Count == 0) { _logger.Warn("Vob size filter resulted in zero matches. Taking all vobs."); files = allVobs; } // Assuming they're named "vts_05_01", take all files whose second part matches that of the first file if (files.Count > 0) { var parts = _fileSystem.GetFileNameWithoutExtension(files[0]).Split('_'); if (parts.Length == 3) { var title = parts[1]; files = files.TakeWhile(f => { var fileParts = _fileSystem.GetFileNameWithoutExtension(f).Split('_'); return(fileParts.Length == 3 && string.Equals(title, fileParts[1], StringComparison.OrdinalIgnoreCase)); }).ToList(); // If this resulted in not getting any vobs, just take them all if (files.Count == 0) { _logger.Warn("Vob filename filter resulted in zero matches. Taking all vobs."); files = allVobs; } } } return(files.Select(i => i.FullName)); }
/// <summary> /// Gets the input argument. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>System.String.</returns> protected string GetInputArgument(BaseItem item, IIsoMount isoMount) { var type = InputType.AudioFile; var inputPath = new[] { item.Path }; var video = item as Video; if (video != null) { if (!(video.VideoType == VideoType.Iso && isoMount == null)) { inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type); } } return MediaEncoder.GetInputArgument(inputPath, type); }
/// <summary> /// Gets the command arguments. /// </summary> /// <param name="items">The items.</param> /// <param name="formatString">The format string.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>System.String.</returns> protected string GetCommandArguments(IEnumerable<BaseItemDto> items, string formatString, IIsoMount isoMount) { var list = items.ToList(); string path; if (list.Count == 1 || !SupportsMultiFilePlayback || isoMount != null) { path = "\"" + GetPathForCommandLine(list[0], isoMount) + "\""; } else { var paths = list.Select(i => "\"" + GetPathForCommandLine(i, null) + "\""); path = string.Join(" ", paths.ToArray()); } return formatString.Replace("{PATH}", path); }
/// <summary> /// Gets the playable path. /// </summary> /// <param name="item">The item.</param> /// <param name="isoMount">The iso mount.</param> /// <param name="apiClient">The API client.</param> /// <param name="startTimeTicks">The start time ticks.</param> /// <returns>System.String.</returns> public static PlayableItem GetPlayableItem(BaseItemDto item, List<MediaSourceInfo> mediaSources, IIsoMount isoMount, IApiClient apiClient, long? startTimeTicks, int? maxBitrate) { // Check the mounted path first if (isoMount != null) { if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay) { return new PlayableItem { OriginalItem = item, PlayablePath = GetBlurayPath(isoMount.MountedPath), IsoMount = isoMount, MediaSource = item.MediaSources.First() }; } return new PlayableItem { OriginalItem = item, PlayablePath = isoMount.MountedPath, IsoMount = isoMount, MediaSource = item.MediaSources.First() }; } if (item.LocationType == LocationType.FileSystem) { if (File.Exists(item.Path) || Directory.Exists(item.Path)) { if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay) { return new PlayableItem { OriginalItem = item, PlayablePath = GetBlurayPath(item.Path), MediaSource = item.MediaSources.First() }; } if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Dvd) { return new PlayableItem { OriginalItem = item, PlayablePath = item.Path, MediaSource = item.MediaSources.First() }; } if (item.VideoType.HasValue && item.VideoType.Value == VideoType.HdDvd) { return new PlayableItem { OriginalItem = item, PlayablePath = item.Path, MediaSource = item.MediaSources.First() }; } //return item.Path; } } return GetStreamedItem(item, mediaSources, apiClient, startTimeTicks, maxBitrate); }