private void btnPreview_Click(object sender, EventArgs e)
        {
            var filePaths = txbFilePath.Text.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

            if (filePaths.Length == 0)
            {
                MessageBox.Show("未选择字幕文件");
                return;
            }
            SubtitleFiles.Clear();

            stOperator = SubtitleHelper.GetOperatorByFileName(filePaths[0]);
            foreach (var filePath in filePaths)
            {
                var content = FileOperationHelper.ReadFile(filePath);
                var srts    = stOperator.Parse(content);
                SubtitleFiles.Add(filePath, srts);
            }
            richTextBox1.Clear();
            foreach (var subtitleFile in SubtitleFiles)
            {
                richTextBox1.AppendText("----" + subtitleFile.Key + "----\r\n");
                richTextBox1.AppendText(stOperator.Subtitle2String(subtitleFile.Value));
            }
        }
Ejemplo n.º 2
0
        private static async Task <bool> SendSegmentAsync(string fileName, IOwinContext context, StreamItem streamItem)
        {
            if (!string.IsNullOrEmpty(fileName) && streamItem.StreamContext is TranscodeContext tc)
            {
                using (await streamItem.RequestBusyLockAsync(SendDataCancellation.Token))
                {
                    var segment = await MediaConverter.GetSegmentFileAsync((VideoTranscoding)streamItem.TranscoderObject.TranscodingParameter, tc, fileName);

                    if (segment != null)
                    {
                        if (segment.Value.ContainerEnum is VideoContainer)
                        {
                            VideoTranscoding video    = (VideoTranscoding)streamItem.TranscoderObject.TranscodingParameter;
                            List <string>    profiles = ProfileMime.ResolveVideoProfile((VideoContainer)segment.Value.ContainerEnum, video.TargetVideoCodec, video.TargetAudioCodec, EncodingProfile.Unknown, 0, 0, 0, 0, 0, 0, Timestamp.None);
                            string           mime     = "video/unknown";
                            ProfileMime.FindCompatibleMime(streamItem.Profile, profiles, ref mime);
                            context.Response.ContentType = mime;
                        }
                        else if (segment.Value.ContainerEnum is SubtitleCodec)
                        {
                            context.Response.ContentType = SubtitleHelper.GetSubtitleMime((SubtitleCodec)segment.Value.ContainerEnum);
                        }
                        bool onlyHeaders = context.Request.Method == "HEAD" || context.Response.StatusCode == (int)HttpStatusCode.NotModified;
                        Logger.Debug("RetrieveStream: Sending file header only: {0}", onlyHeaders.ToString());

                        await SendWholeFileAsync(context, segment.Value.FileData, onlyHeaders);

                        // Close the Stream so that FFMpeg can replace the playlist file
                        segment.Value.FileData.Dispose();
                        return(true);
                    }
                }
            }
            return(false);
        }
Ejemplo n.º 3
0
        private void btnPickupNewWords_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            SentenceParse sentenceParse = new SentenceParse();
            DirectoryInfo directoryInfo = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
            List <string> sentences     = new List <string>();

            foreach (FileInfo fileInfo in directoryInfo.GetFiles())
            {
                string filePath   = fileInfo.FullName;
                var    txt        = FileOperationHelper.ReadFile(filePath);
                var    stOperator = SubtitleHelper.GetOperatorByFileName(filePath);
                var    srts       = stOperator.Parse(txt);

                srts = stOperator.RemoveChinese(srts);
                sentences.AddRange(srts.Bodies.Values.Select(l => l.EnglishText));
            }

            Splash.Show();
            Splash.Status = "解析字幕中...";
            IDictionary <string, VPreviewWord> previewWords = new Dictionary <string, VPreviewWord>();

            foreach (var sentence in sentences)
            {
                var newWords = sentenceParse.Pickup(sentence);
                foreach (KeyValuePair <string, string> keyValuePair in newWords)
                {
                    string original = keyValuePair.Key;
                    string word     = keyValuePair.Value;
                    if (previewWords.ContainsKey(original))
                    {
                        previewWords[original].Rank++;
                    }
                    else
                    {
                        var mean = sentenceParse.RemarkWord(sentence, word, original);
                        if (mean != null)
                        {
                            var wd = new VPreviewWord()
                            {
                                Word     = mean.Word,
                                Rank     = 1,
                                Sentence = sentence,
                                Mean     =
                                    mean.DefaultMean == null ? mean.Means[0].ToString() : mean.DefaultMean.ToString()
                            };
                            previewWords.Add(original, wd);
                        }
                    }
                }
            }
            DisplayPreviewWords(previewWords.Values);

            Splash.Close();
        }
Ejemplo n.º 4
0
 public Media(string fileName, string path)
 {
     Path          = path;
     FileName      = fileName;
     ShowName      = SeriesHelper.GetTitle(fileName);
     EpisodeNumber = SeriesHelper.GetEpisodeNumber(fileName);
     SeasonNumber  = SeriesHelper.GetSeasonNumber(fileName);
     Releaser      = SubtitleHelper.GetReleaser(fileName);
     Quality       = SubtitleHelper.GetQuality(fileName);
 }
Ejemplo n.º 5
0
        private void btnParse_Click(object sender, EventArgs e)
        {
            var txt = FileOperationHelper.ReadFile(txbSubtitleFilePath.Text);

            stOperator = SubtitleHelper.GetOperatorByFileName(txbSubtitleFilePath.Text);
            var srts = stOperator.Parse(txt);

            srts = stOperator.RemoveChinese(srts);

            ShowSubtitleText(srts.Bodies);
            subtitle = srts;
        }
Ejemplo n.º 6
0
        private void ReadAndShowSubtitle()
        {
            var txt = FileOperationHelper.ReadFile(txbSubtitleFilePath.Text);

            stOperator = SubtitleHelper.GetOperatorByFileName(txbSubtitleFilePath.Text);
            var srts = stOperator.Parse(txt);

            srts = stOperator.RemoveChinese(srts);
            srts = stOperator.RemoveFormat(srts);
            ShowSubtitleText(srts.Bodies.Values);
            subtitle = srts;
        }
Ejemplo n.º 7
0
        public bool RefreshMediaInfo()
        {
            try
            {
                logger.Trace("Getting media info for: {0}", FullServerPath ?? VideoLocal_Place_ID.ToString());
                MediaContainer m = null;
                if (VideoLocal == null)
                {
                    logger.Error($"VideoLocal for {FullServerPath ?? VideoLocal_Place_ID.ToString()} failed to be retrived for MediaInfo");
                    return(false);
                }

                if (FullServerPath != null)
                {
                    if (GetFile() == null)
                    {
                        logger.Error($"File {FullServerPath ?? VideoLocal_Place_ID.ToString()} failed to be retrived for MediaInfo");
                        return(false);
                    }

                    string name = FullServerPath.Replace("/", $"{Path.DirectorySeparatorChar}");
                    m = Utilities.MediaInfoLib.MediaInfo.GetMediaInfo(name); //Mediainfo should have libcurl.dll for http
                    var duration = m?.GeneralStream?.Duration ?? 0;
                    if (duration == 0)
                    {
                        m = null;
                    }
                }


                if (m != null)
                {
                    SVR_VideoLocal info = VideoLocal;

                    List <TextStream> subs = SubtitleHelper.GetSubtitleStreams(this);
                    if (subs.Count > 0)
                    {
                        m.media.track.AddRange(subs);
                    }
                    info.Media = m;
                    return(true);
                }
                logger.Error($"File {FullServerPath ?? VideoLocal_Place_ID.ToString()} failed to read MediaInfo");
            }
            catch (Exception e)
            {
                logger.Error($"Unable to read the media information of file {FullServerPath ?? VideoLocal_Place_ID.ToString()} ERROR: {e}");
            }
            return(false);
        }
        public static string GetSubtitleBaseURL(Guid mediaItemId, EndPointSettings client, out string subMime, out string subExtension)
        {
            SubtitleCodec codec = SubtitleCodec.Unknown;

            subMime      = null;
            subExtension = null;

            if (UseSoftCodedSubtitle(client, out codec, out subMime) == true)
            {
                subExtension = SubtitleHelper.GetSubtitleExtension(codec);
                string subType = codec.ToString();
                return(string.Format(GetBaseResourceURL()
                                     + GetResourceUrl(mediaItemId.ToString(), client.ClientId)
                                     + "&aspect=SUBTITLE&type={0}&file=subtitle.{1}", subType, subExtension));
            }
            return(null);
        }
 public static bool UseSoftCodedSubtitle(EndPointSettings client, out SubtitleCodec targetCodec, out string targetMime)
 {
     targetCodec = SubtitleCodec.Unknown;
     targetMime  = "text/plain";
     if (client.Profile.MediaTranscoding.SubtitleSettings.SubtitleMode == SubtitleSupport.SoftCoded)
     {
         targetCodec = client.Profile.MediaTranscoding.SubtitleSettings.SubtitlesSupported[0].Format;
         if (string.IsNullOrEmpty(client.Profile.MediaTranscoding.SubtitleSettings.SubtitlesSupported[0].Mime) == false)
         {
             targetMime = client.Profile.MediaTranscoding.SubtitleSettings.SubtitlesSupported[0].Mime;
         }
         else
         {
             targetMime = SubtitleHelper.GetSubtitleMime(targetCodec);
         }
         return(true);
     }
     return(false);
 }
Ejemplo n.º 10
0
        // returns false if we should retry
        private bool MoveFileIfRequired(bool deleteEmpty = true)
        {
            // TODO move A LOT of this into renamer helper methods. A renamer can do them optionally
            if (!ServerSettings.Instance.Import.MoveOnImport)
            {
                logger.Trace($"Skipping move of \"{this.FullServerPath}\" as move on import is disabled");
                return(true);
            }

            // TODO Make this take an argument to disable removing empty dirs. It's slow, and should only be done if needed
            try
            {
                logger.Trace($"Attempting to MOVE file: \"{FullServerPath ?? VideoLocal_Place_ID.ToString()}\"");

                if (FullServerPath == null)
                {
                    logger.Error($"Could not find or access the file to move: {VideoLocal_Place_ID}");
                    return(true);
                }

                // check if this file is in the drop folder
                // otherwise we don't need to move it
                if (ImportFolder.IsDropSource == 0)
                {
                    logger.Trace($"Not moving file as it is NOT in the drop folder: \"{FullServerPath}\"");
                    return(true);
                }

                if (!File.Exists(FullServerPath))
                {
                    logger.Error($"Could not find or access the file to move: \"{FullServerPath}\"");
                    // this can happen due to file locks, so retry
                    return(false);
                }
                var sourceFile = new FileInfo(FullServerPath);

                // find the default destination
                (var destImpl, string newFolderPath) = RenameFileHelper.GetDestination(this, null);

                if (!(destImpl is SVR_ImportFolder destFolder))
                {
                    // In this case, an error string was returned, but we'll suppress it and give an error elsewhere
                    if (newFolderPath != null)
                    {
                        return(true);
                    }
                    logger.Error($"Could not find a valid destination: \"{FullServerPath}\"");
                    return(true);
                }

                // keep the original drop folder for later (take a copy, not a reference)
                SVR_ImportFolder dropFolder = ImportFolder;

                if (string.IsNullOrEmpty(newFolderPath))
                {
                    return(true);
                }

                // We've already resolved FullServerPath, so it doesn't need to be checked
                string newFilePath       = Path.Combine(newFolderPath, Path.GetFileName(FullServerPath));
                string newFullServerPath = Path.Combine(destFolder.ImportFolderLocation, newFilePath);

                var destFullTree = Path.Combine(destFolder.ImportFolderLocation, newFolderPath);
                if (!Directory.Exists(destFullTree))
                {
                    try
                    {
                        Directory.CreateDirectory(destFullTree);
                    }
                    catch (Exception e)
                    {
                        logger.Error(e);
                        return(true);
                    }
                }

                // Last ditch effort to ensure we aren't moving a file unto itself
                if (newFullServerPath.Equals(FullServerPath, StringComparison.InvariantCultureIgnoreCase))
                {
                    logger.Error($"Resolved to move \"{newFullServerPath}\" unto itself. NOT MOVING");
                    return(true);
                }

                var originalFileName = FullServerPath;
                var textStreams      = SubtitleHelper.GetSubtitleStreams(this);

                if (File.Exists(newFullServerPath))
                {
                    // A file with the same name exists at the destination.
                    // Handle Duplicate Files, A duplicate file record won't exist yet,
                    // so we'll check the old fashioned way
                    logger.Trace("A file already exists at the new location, checking it for duplicate");
                    var destVideoLocalPlace = RepoFactory.VideoLocalPlace.GetByFilePathAndImportFolderID(newFilePath,
                                                                                                         destFolder.ImportFolderID);
                    var destVideoLocal = destVideoLocalPlace?.VideoLocal;
                    if (destVideoLocal == null)
                    {
                        logger.Error("The existing file at the new location does not have a VideoLocal. Not moving");
                        return(true);
                    }
                    if (destVideoLocal.Hash == VideoLocal.Hash)
                    {
                        logger.Info($"Not moving file as it already exists at the new location, deleting source file instead: \"{FullServerPath}\" --- \"{newFullServerPath}\"");

                        // if the file already exists, we can just delete the source file instead
                        // this is safer than deleting and moving
                        try
                        {
                            sourceFile.Delete();
                        }
                        catch (Exception e)
                        {
                            logger.Warn($"Unable to DELETE file: \"{FullServerPath}\" error {e}");
                            RemoveRecord(false);

                            // check for any empty folders in drop folder
                            // only for the drop folder
                            if (dropFolder.IsDropSource != 1)
                            {
                                return(true);
                            }
                            RecursiveDeleteEmptyDirectories(dropFolder?.ImportFolderLocation, true);
                            return(true);
                        }
                    }

                    // Not a dupe, don't delete it
                    logger.Trace("A file already exists at the new location, checking it for version and group");
                    var destinationExistingAniDBFile = destVideoLocal.GetAniDBFile();
                    if (destinationExistingAniDBFile == null)
                    {
                        logger.Error("The existing file at the new location does not have AniDB info. Not moving.");
                        return(true);
                    }

                    var aniDBFile = VideoLocal.GetAniDBFile();
                    if (aniDBFile == null)
                    {
                        logger.Error("The file does not have AniDB info. Not moving.");
                        return(true);
                    }

                    if (destinationExistingAniDBFile.Anime_GroupName == aniDBFile.Anime_GroupName &&
                        destinationExistingAniDBFile.FileVersion < aniDBFile.FileVersion)
                    {
                        // This is a V2 replacing a V1 with the same name.
                        // Normally we'd let the Multiple Files Utility handle it, but let's just delete the V1
                        logger.Info("The existing file is a V1 from the same group. Replacing it.");
                        // Delete the destination
                        (bool success, string _) = destVideoLocalPlace.RemoveAndDeleteFile();
                        if (!success)
                        {
                            return(false);
                        }

                        // Move
                        ShokoServer.PauseWatchingFiles();
                        logger.Info($"Moving file from \"{FullServerPath}\" to \"{newFullServerPath}\"");
                        try
                        {
                            sourceFile.MoveTo(newFullServerPath);
                        }
                        catch (Exception e)
                        {
                            logger.Error($"Unable to MOVE file: \"{FullServerPath}\" to \"{newFullServerPath}\" error {e}");
                            ShokoServer.UnpauseWatchingFiles();
                            return(false);
                        }

                        // Handle Duplicate Files
                        var dups = RepoFactory.DuplicateFile.GetByFilePathAndImportFolder(FilePath, ImportFolderID).ToList();

                        foreach (var dup in dups)
                        {
                            // Move source
                            if (dup.FilePathFile1.Equals(FilePath) && dup.ImportFolderIDFile1 == ImportFolderID)
                            {
                                dup.FilePathFile1       = newFilePath;
                                dup.ImportFolderIDFile1 = destFolder.ImportFolderID;
                            }
                            else if (dup.FilePathFile2.Equals(FilePath) && dup.ImportFolderIDFile2 == ImportFolderID)
                            {
                                dup.FilePathFile2       = newFilePath;
                                dup.ImportFolderIDFile2 = destFolder.ImportFolderID;
                            }
                            // validate the dup file
                            // There are cases where a dup file was not cleaned up before, so we'll do it here, too
                            if (!dup.GetFullServerPath1()
                                .Equals(dup.GetFullServerPath2(), StringComparison.InvariantCultureIgnoreCase))
                            {
                                RepoFactory.DuplicateFile.Save(dup);
                            }
                            else
                            {
                                RepoFactory.DuplicateFile.Delete(dup);
                            }
                        }

                        ImportFolderID = destFolder.ImportFolderID;
                        FilePath       = newFilePath;
                        RepoFactory.VideoLocalPlace.Save(this);

                        // check for any empty folders in drop folder
                        // only for the drop folder
                        if (dropFolder.IsDropSource == 1 && deleteEmpty)
                        {
                            RecursiveDeleteEmptyDirectories(dropFolder?.ImportFolderLocation, true);
                        }
                    }
                }
                else
                {
                    ShokoServer.PauseWatchingFiles();
                    logger.Info($"Moving file from \"{FullServerPath}\" to \"{newFullServerPath}\"");
                    try
                    {
                        sourceFile.MoveTo(newFullServerPath);
                    }
                    catch (Exception e)
                    {
                        logger.Error($"Unable to MOVE file: \"{FullServerPath}\" to \"{newFullServerPath}\" error {e}");
                        ShokoServer.UnpauseWatchingFiles();
                        return(false);
                    }

                    // Handle Duplicate Files
                    var dups = RepoFactory.DuplicateFile.GetByFilePathAndImportFolder(FilePath, ImportFolderID).ToList();

                    foreach (var dup in dups)
                    {
                        // Move source
                        if (dup.FilePathFile1.Equals(FilePath) && dup.ImportFolderIDFile1 == ImportFolderID)
                        {
                            dup.FilePathFile1       = newFilePath;
                            dup.ImportFolderIDFile1 = destFolder.ImportFolderID;
                        }
                        else if (dup.FilePathFile2.Equals(FilePath) && dup.ImportFolderIDFile2 == ImportFolderID)
                        {
                            dup.FilePathFile2       = newFilePath;
                            dup.ImportFolderIDFile2 = destFolder.ImportFolderID;
                        }
                        // validate the dup file
                        // There are cases where a dup file was not cleaned up before, so we'll do it here, too
                        if (!dup.GetFullServerPath1()
                            .Equals(dup.GetFullServerPath2(), StringComparison.InvariantCultureIgnoreCase))
                        {
                            RepoFactory.DuplicateFile.Save(dup);
                        }
                        else
                        {
                            RepoFactory.DuplicateFile.Delete(dup);
                        }
                    }

                    ImportFolderID = destFolder.ImportFolderID;
                    FilePath       = newFilePath;
                    RepoFactory.VideoLocalPlace.Save(this);

                    // check for any empty folders in drop folder
                    // only for the drop folder
                    if (dropFolder.IsDropSource == 1 && deleteEmpty)
                    {
                        RecursiveDeleteEmptyDirectories(dropFolder?.ImportFolderLocation, true);
                    }
                }

                try
                {
                    // move any subtitle files
                    foreach (TextStream subtitleFile in textStreams)
                    {
                        if (string.IsNullOrEmpty(subtitleFile.Filename))
                        {
                            continue;
                        }
                        var newParent = Path.GetDirectoryName(newFullServerPath);
                        var srcParent = Path.GetDirectoryName(originalFileName);
                        if (string.IsNullOrEmpty(newParent) || string.IsNullOrEmpty(srcParent))
                        {
                            continue;
                        }
                        var subPath = Path.Combine(srcParent, subtitleFile.Filename);
                        if (!File.Exists(subPath))
                        {
                            continue;
                        }
                        var    subFile    = new FileInfo(subPath);
                        string newSubPath = Path.Combine(newParent, subFile.Name);
                        if (File.Exists(newSubPath))
                        {
                            try
                            {
                                File.Delete(newSubPath);
                            }
                            catch (Exception e)
                            {
                                logger.Warn($"Unable to DELETE file: \"{subtitleFile}\" error {e}");
                            }
                        }

                        try
                        {
                            subFile.MoveTo(newSubPath);
                        }
                        catch (Exception e)
                        {
                            logger.Error($"Unable to MOVE file: \"{subtitleFile}\" to \"{newSubPath}\" error {e}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    logger.Error(ex, ex.ToString());
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex, $"Could not MOVE file: \"{FullServerPath ?? VideoLocal_Place_ID.ToString()}\" -- {ex}");
            }
            ShokoServer.UnpauseWatchingFiles();
            return(true);
        }
Ejemplo n.º 11
0
        // TODO Merge these, with proper logic depending on the scenario (import, force, etc)
        public (string, string) MoveWithResultString(string scriptName, bool force = false)
        {
            // TODO Make this take an argument to disable removing empty dirs. It's slow, and should only be done if needed
            if (FullServerPath == null)
            {
                logger.Error($"Could not find or access the file to move: {VideoLocal_Place_ID}");
                return(string.Empty, "ERROR: Unable to access file");
            }

            if (!File.Exists(FullServerPath))
            {
                logger.Error($"Could not find or access the file to move: \"{FullServerPath}\"");
                // this can happen due to file locks, so retry
                return(string.Empty, "ERROR: Could not access the file");
            }

            FileInfo sourceFile = new FileInfo(FullServerPath);

            // There is a possibility of weird logic based on source of the file. Some handling should be made for it....later
            (var destImpl, string newFolderPath) = RenameFileHelper.GetDestination(this, scriptName);

            if (!(destImpl is SVR_ImportFolder destFolder))
            {
                // In this case, an error string was returned, but we'll suppress it and give an error elsewhere
                if (newFolderPath != null)
                {
                    logger.Error($"Unable to find destination for: \"{FullServerPath}\"");
                    logger.Error($"The error message was: {newFolderPath}");
                    return(string.Empty, "ERROR: " + newFolderPath);
                }
                logger.Error($"Unable to find destination for: \"{FullServerPath}\"");
                return(string.Empty, "ERROR: There was an error but no error code returned...");
            }

            // keep the original drop folder for later (take a copy, not a reference)
            SVR_ImportFolder dropFolder = ImportFolder;

            if (string.IsNullOrEmpty(newFolderPath))
            {
                logger.Error($"Unable to find destination for: \"{FullServerPath}\"");
                return(string.Empty, "ERROR: The returned path was null or empty");
            }

            // We've already resolved FullServerPath, so it doesn't need to be checked
            string newFilePath       = Path.Combine(newFolderPath, Path.GetFileName(FullServerPath));
            string newFullServerPath = Path.Combine(destFolder.ImportFolderLocation, newFilePath);

            var destFullTree = Path.Combine(destFolder.ImportFolderLocation, newFolderPath);

            if (!Directory.Exists(destFullTree))
            {
                try
                {
                    Directory.CreateDirectory(destFullTree);
                }
                catch (Exception e)
                {
                    logger.Error(e);
                    return(string.Empty, $"ERROR: Unable to create directory tree: \"{destFullTree}\"");
                }
            }

            // Last ditch effort to ensure we aren't moving a file unto itself
            if (newFullServerPath.Equals(FullServerPath, StringComparison.InvariantCultureIgnoreCase))
            {
                logger.Info($"Moving file SKIPPED! The file is already at its desired location: \"{FullServerPath}\"");
                return(newFolderPath, string.Empty);
            }

            if (File.Exists(newFullServerPath))
            {
                logger.Error($"A file already exists at the desired location: \"{FullServerPath}\"");
                return(string.Empty, "ERROR: A file already exists at the destination");
            }

            ShokoServer.PauseWatchingFiles();

            logger.Info($"Moving file from \"{FullServerPath}\" to \"{newFullServerPath}\"");
            try
            {
                sourceFile.MoveTo(newFullServerPath);
            }
            catch (Exception e)
            {
                logger.Error($"Unable to MOVE file: \"{FullServerPath}\" to \"{newFullServerPath}\" error {e}");
                ShokoServer.UnpauseWatchingFiles();
                return(newFullServerPath, "ERROR: " + e);
            }

            // Save for later. Scan for subtitles while the vlplace is still set for the source location
            string originalFileName = FullServerPath;
            var    textStreams      = SubtitleHelper.GetSubtitleStreams(this);

            // Handle Duplicate Files
            var dups = RepoFactory.DuplicateFile.GetByFilePathAndImportFolder(FilePath, ImportFolderID).ToList();

            foreach (var dup in dups)
            {
                // Move source
                if (dup.FilePathFile1.Equals(FilePath) && dup.ImportFolderIDFile1 == ImportFolderID)
                {
                    dup.FilePathFile1       = newFilePath;
                    dup.ImportFolderIDFile1 = destFolder.ImportFolderID;
                }
                else if (dup.FilePathFile2.Equals(FilePath) && dup.ImportFolderIDFile2 == ImportFolderID)
                {
                    dup.FilePathFile2       = newFilePath;
                    dup.ImportFolderIDFile2 = destFolder.ImportFolderID;
                }
                // validate the dup file
                // There are cases where a dup file was not cleaned up before, so we'll do it here, too
                if (!dup.GetFullServerPath1()
                    .Equals(dup.GetFullServerPath2(), StringComparison.InvariantCultureIgnoreCase))
                {
                    RepoFactory.DuplicateFile.Save(dup);
                }
                else
                {
                    RepoFactory.DuplicateFile.Delete(dup);
                }
            }

            ImportFolderID = destFolder.ImportFolderID;
            FilePath       = newFilePath;
            RepoFactory.VideoLocalPlace.Save(this);

            try
            {
                // move any subtitle files
                foreach (TextStream subtitleFile in textStreams)
                {
                    if (string.IsNullOrEmpty(subtitleFile.Filename))
                    {
                        continue;
                    }
                    var newParent = Path.GetDirectoryName(newFullServerPath);
                    var srcParent = Path.GetDirectoryName(originalFileName);
                    if (string.IsNullOrEmpty(newParent) || string.IsNullOrEmpty(srcParent))
                    {
                        continue;
                    }
                    var subPath = Path.Combine(srcParent, subtitleFile.Filename);
                    if (!File.Exists(subPath))
                    {
                        continue;
                    }
                    var    subFile    = new FileInfo(subPath);
                    string newSubPath = Path.Combine(newParent, subFile.Name);
                    if (File.Exists(newSubPath))
                    {
                        try
                        {
                            File.Delete(newSubPath);
                        }
                        catch (Exception e)
                        {
                            logger.Warn($"Unable to DELETE file: \"{subtitleFile}\" error {e}");
                        }
                    }

                    try
                    {
                        subFile.MoveTo(newSubPath);
                    }
                    catch (Exception e)
                    {
                        logger.Error($"Unable to MOVE file: \"{subtitleFile}\" to \"{newSubPath}\" error {e}");
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex, ex.ToString());
            }

            // check for any empty folders in drop folder
            // only for the drop folder
            if (dropFolder.IsDropSource == 1)
            {
                RecursiveDeleteEmptyDirectories(dropFolder?.ImportFolderLocation, true);
            }
            ShokoServer.UnpauseWatchingFiles();
            return(newFolderPath, string.Empty);
        }
Ejemplo n.º 12
0
        // returns false if we should try again after the timer
        // TODO Generify this and Move and make a return model instead of tuple
        public (bool, string, string) RenameFile(bool preview = false, string scriptName = null)
        {
            if (scriptName != null && scriptName.Equals(Shoko.Models.Constants.Renamer.TempFileName))
            {
                return(true, string.Empty, "Error: Do not attempt to use a temp file to rename.");
            }
            if (ImportFolder == null)
            {
                logger.Error($"Error: The renamer can't get the import folder for ImportFolderID: {ImportFolderID}, File: \"{FilePath}\"");
                return(true, string.Empty, "Error: Could not find the file");
            }

            string renamed = RenameFileHelper.GetFilename(this, scriptName);

            if (string.IsNullOrEmpty(renamed))
            {
                logger.Error($"Error: The renamer returned a null or empty name for: \"{FilePath}\"");
                return(true, string.Empty, "Error: The file renamer returned a null or empty value");
            }

            if (renamed.StartsWith("*Error: "))
            {
                logger.Error($"Error: The renamer returned an error on file: \"{FilePath}\"\n            {renamed}");
                return(true, string.Empty, renamed.Substring(1));
            }

            // actually rename the file
            string fullFileName = FullServerPath;

            // check if the file exists
            if (string.IsNullOrEmpty(fullFileName))
            {
                logger.Error($"Error could not find the original file for renaming, or it is in use: \"{fullFileName}\"");
                return(false, renamed, "Error: Could not access the file");
            }

            if (!File.Exists(fullFileName))
            {
                logger.Error($"Error could not find the original file for renaming, or it is in use: \"{fullFileName}\"");
                return(false, renamed, "Error: Could not access the file");
            }

            // actually rename the file
            string path        = Path.GetDirectoryName(fullFileName);
            string newFullName = Path.Combine(path, renamed);
            var    textStreams = SubtitleHelper.GetSubtitleStreams(this);

            try
            {
                if (fullFileName.Equals(newFullName, StringComparison.InvariantCultureIgnoreCase))
                {
                    logger.Info($"Renaming file SKIPPED! no change From \"{fullFileName}\" to \"{newFullName}\"");
                    return(true, renamed, string.Empty);
                }

                if (File.Exists(newFullName))
                {
                    logger.Info($"Renaming file SKIPPED! Destination Exists \"{newFullName}\"");
                    return(true, renamed, "Error: The filename already exists");
                }
                if (preview)
                {
                    return(false, renamed, string.Empty);
                }

                ShokoServer.PauseWatchingFiles();

                logger.Info($"Renaming file From \"{fullFileName}\" to \"{newFullName}\"");
                try
                {
                    var file = new FileInfo(fullFileName);
                    file.MoveTo(newFullName);
                }
                catch (Exception e)
                {
                    logger.Info($"Renaming file FAILED! From \"{fullFileName}\" to \"{newFullName}\" - {e}");
                    ShokoServer.UnpauseWatchingFiles();
                    return(false, renamed, "Error: Failed to rename file");
                }

                // Rename external subs!
                var oldBasename = Path.GetFileNameWithoutExtension(fullFileName);
                var newBasename = Path.GetFileNameWithoutExtension(renamed);
                foreach (TextStream sub in textStreams)
                {
                    if (string.IsNullOrEmpty(sub.Filename))
                    {
                        continue;
                    }
                    var oldSubPath = Path.Combine(path, sub.Filename);

                    if (!File.Exists(oldSubPath))
                    {
                        logger.Error($"Unable to rename external subtitle \"{sub.Filename}\". Cannot access the file");
                        continue;
                    }
                    var newSub = sub.Filename.Replace(oldBasename, newBasename);
                    try
                    {
                        var file = new FileInfo(oldSubPath);
                        file.MoveTo(newSub);
                    }
                    catch (Exception e)
                    {
                        logger.Error($"Unable to rename external subtitle \"{sub.Filename}\" to \"{newSub}\". {e}");
                    }
                }

                logger.Info($"Renaming file SUCCESS! From \"{fullFileName}\" to \"{newFullName}\"");
                Tuple <SVR_ImportFolder, string> tup = VideoLocal_PlaceRepository.GetFromFullPath(newFullName);
                if (tup == null)
                {
                    logger.Error($"Unable to LOCATE file \"{newFullName}\" inside the import folders");
                    ShokoServer.UnpauseWatchingFiles();
                    return(false, renamed, "Error: Unable to resolve new path");
                }

                // Before we change all references, remap Duplicate Files
                List <DuplicateFile> dups = RepoFactory.DuplicateFile.GetByFilePathAndImportFolder(FilePath, ImportFolderID);
                if (dups != null && dups.Count > 0)
                {
                    foreach (var dup in dups)
                    {
                        bool dupchanged = false;
                        if (dup.FilePathFile1.Equals(FilePath, StringComparison.InvariantCultureIgnoreCase) &&
                            dup.ImportFolderIDFile1 == ImportFolderID)
                        {
                            dup.FilePathFile1 = tup.Item2;
                            dupchanged        = true;
                        }
                        else if (dup.FilePathFile2.Equals(FilePath, StringComparison.InvariantCultureIgnoreCase) &&
                                 dup.ImportFolderIDFile2 == ImportFolderID)
                        {
                            dup.FilePathFile2 = tup.Item2;
                            dupchanged        = true;
                        }
                        if (dupchanged)
                        {
                            RepoFactory.DuplicateFile.Save(dup);
                        }
                    }
                }
                // Rename hash xrefs
                var filenameHash = RepoFactory.FileNameHash.GetByHash(VideoLocal.Hash);
                if (!filenameHash.Any(a => a.FileName.Equals(renamed)))
                {
                    FileNameHash fnhash = new FileNameHash
                    {
                        DateTimeUpdated = DateTime.Now,
                        FileName        = renamed,
                        FileSize        = VideoLocal.FileSize,
                        Hash            = VideoLocal.Hash
                    };
                    RepoFactory.FileNameHash.Save(fnhash);
                }

                FilePath = tup.Item2;
                RepoFactory.VideoLocalPlace.Save(this);
                // just in case
                VideoLocal.FileName = renamed;
                RepoFactory.VideoLocal.Save(VideoLocal, false);
            }
            catch (Exception ex)
            {
                logger.Info($"Renaming file FAILED! From \"{fullFileName}\" to \"{newFullName}\" - {ex.Message}");
                logger.Error(ex, ex.ToString());
                return(true, string.Empty, $"Error: {ex.Message}");
            }
            ShokoServer.UnpauseWatchingFiles();
            return(true, renamed, string.Empty);
        }
Ejemplo n.º 13
0
        private static void PopulateVideoEpisodeFromVideoLocal(Video l, VideoLocal v, JMMType type, int userid)
        {
            l.Type                  = "episode";
            l.Summary               = "Episode Overview Not Available"; //TODO Intenationalization
            l.Title                 = Path.GetFileNameWithoutExtension(v.FilePath);
            l.Key                   = ContructVideoLocalIdUrl(userid, v.VideoLocalID, type);
            l.AddedAt               = v.DateTimeCreated.ToUnixTime();
            l.UpdatedAt             = v.DateTimeUpdated.ToUnixTime();
            l.OriginallyAvailableAt = v.DateTimeCreated.ToPlexDate();
            l.Year                  = v.DateTimeCreated.Year.ToString();
            VideoInfo info = v.VideoInfo;

            Media m = null;

            if (info != null)
            {
                if (!string.IsNullOrEmpty(info.FullInfo))
                {
                    try
                    {
                        m = XmlDeserializeFromString <Media>(info.FullInfo);
                    }
                    catch (Exception)
                    {
                        info.FullInfo = null;
                    }
                }
                if (string.IsNullOrEmpty(info.FullInfo))
                {
                    VideoInfoRepository repo  = new VideoInfoRepository();
                    MediaInfoResult     mInfo = FileHashHelper.GetMediaInfo(v.FullServerPath, true);
                    info.AudioBitrate    = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate;
                    info.AudioCodec      = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec;
                    info.Duration        = mInfo.Duration;
                    info.VideoBitrate    = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate;
                    info.VideoBitDepth   = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth;
                    info.VideoCodec      = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec;
                    info.VideoFrameRate  = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate;
                    info.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution;
                    info.FullInfo        = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo;
                    repo.Save(info);
                    m = XmlDeserializeFromString <Media>(info.FullInfo);
                }
            }
            l.Medias = new List <Media>();
            if (m != null)
            {
                m.Id = null;
                List <JMMContracts.PlexContracts.Stream> subs = SubtitleHelper.GetSubtitleStreams(v.FullServerPath);
                if (subs.Count > 0)
                {
                    foreach (JMMContracts.PlexContracts.Stream s in subs)
                    {
                        s.Key = ConstructFileStream(userid, s.File);
                    }
                    m.Parts[0].Streams.AddRange(subs);
                }
                foreach (Part p in m.Parts)
                {
                    p.Id = null;
                    string ff = Path.GetExtension(v.FullServerPath);
                    p.Key        = ConstructVideoLocalStream(userid, v.VideoLocalID, ff);
                    p.Accessible = "1";
                    p.Exists     = "1";
                    bool vid = false;
                    bool aud = false;
                    bool txt = false;
                    foreach (JMMContracts.PlexContracts.Stream ss in p.Streams.ToArray())
                    {
                        if ((ss.StreamType == "1") && (!vid))
                        {
                            vid = true;
                        }
                        if ((ss.StreamType == "2") && (!aud))
                        {
                            aud         = true;
                            ss.Selected = "1";
                        }
                        if ((ss.StreamType == "3") && (!txt))
                        {
                            txt         = true;
                            ss.Selected = "1";
                        }
                    }
                }

                l.Medias.Add(m);
                l.Duration = m.Duration;
            }
        }
Ejemplo n.º 14
0
        private static void PopulateVideoEpisodeFromVideoLocal(Video l, VideoLocal v, JMMType type)
        {
            l.Type                  = "episode";
            l.Summary               = "Episode Overview Not Available";
            l.Title                 = Path.GetFileNameWithoutExtension(v.FilePath);
            l.Key                   = l.PrimaryExtraKey = ServerUrl(int.Parse(ServerSettings.JMMServerPort), MainWindow.PathAddressKodi + "/GetMetadata/0/" + (int)type + "/" + v.VideoLocalID);
            l.AddedAt               = v.DateTimeCreated.Year.ToString("0000") + "-" + v.DateTimeCreated.Month.ToString("00") + "-" + v.DateTimeCreated.Day.ToString("00") + " " + v.DateTimeCreated.Hour.ToString("00") + ":" + v.DateTimeCreated.Minute.ToString("00") + ":" + v.DateTimeCreated.Millisecond.ToString("00");
            l.UpdatedAt             = v.DateTimeUpdated.Year.ToString("0000") + "-" + v.DateTimeUpdated.Month.ToString("00") + "-" + v.DateTimeUpdated.Day.ToString("00") + " " + v.DateTimeUpdated.Hour.ToString("00") + ":" + v.DateTimeUpdated.Minute.ToString("00") + ":" + v.DateTimeUpdated.Millisecond.ToString("00");
            l.OriginallyAvailableAt = v.DateTimeCreated.Year.ToString("0000") + "-" + v.DateTimeCreated.Month.ToString("00") + "-" + v.DateTimeCreated.Day.ToString("00");
            l.Year                  = v.DateTimeCreated.Year.ToString();

            VideoInfo info = v.VideoInfo;

            Media m = null;

            if (info != null)
            {
                if (!string.IsNullOrEmpty(info.FullInfo))
                {
                    try
                    {
                        m = XmlDeserializeFromString <Media>(info.FullInfo);
                    }
                    catch (Exception)
                    {
                        info.FullInfo = null;
                    }
                }
                if (string.IsNullOrEmpty(info.FullInfo))
                {
                    VideoInfoRepository repo  = new VideoInfoRepository();
                    MediaInfoResult     mInfo = FileHashHelper.GetMediaInfo(v.FullServerPath, true, true);
                    info.AudioBitrate    = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate;
                    info.AudioCodec      = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec;
                    info.Duration        = mInfo.Duration;
                    info.VideoBitrate    = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate;
                    info.VideoBitDepth   = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth;
                    info.VideoCodec      = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec;
                    info.VideoFrameRate  = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate;
                    info.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution;
                    info.FullInfo        = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo;
                    repo.Save(info);
                    m = XmlDeserializeFromString <Media>(info.FullInfo);
                }
            }
            l.Medias = new List <Media>();
            if (m != null)
            {
                m.Id = null;
                List <JMMContracts.KodiContracts.Stream> subs = SubtitleHelper.GetSubtitleStreamsKodi(v.FullServerPath);
                if (subs.Count > 0)
                {
                    foreach (JMMContracts.KodiContracts.Stream s in subs)
                    {
                        s.Key = ServerUrl(int.Parse(ServerSettings.JMMServerFilePort), "file/0/" + Base64EncodeUrl(s.File), KodiObject.IsExternalRequest);
                    }
                    m.Parts[0].Streams.AddRange(subs);
                }
                foreach (Part p in m.Parts)
                {
                    p.Id = null;

                    p.File = v.FullServerPath;
                    string ff = Path.GetExtension(v.FullServerPath);
                    p.Key        = ServerUrl(int.Parse(ServerSettings.JMMServerFilePort), "videolocal/0/" + v.VideoLocalID + "/file" + ff, KodiObject.IsExternalRequest);
                    p.Accessible = "1";
                    p.Exists     = "1";
                    bool vid = false;
                    bool aud = false;
                    bool txt = false;
                    foreach (JMMContracts.KodiContracts.Stream ss in p.Streams.ToArray())
                    {
                        if ((ss.StreamType == "1") && (!vid))
                        {
                            vid = true;
                        }
                        if ((ss.StreamType == "2") && (!aud))
                        {
                            aud         = true;
                            ss.Selected = "1";
                        }
                        if ((ss.StreamType == "3") && (!txt))
                        {
                            txt         = true;
                            ss.Selected = "1";
                        }
                    }
                }

                l.Medias.Add(m);
                l.Duration = m.Duration;
            }
        }
Ejemplo n.º 15
0
        public static Media GenerateMediaFromVideoLocal(VideoLocal v)
        {
            VideoInfo info = v.VideoInfo;
            Media     m    = null;

            if (info != null)
            {
                if (!string.IsNullOrEmpty(info.FullInfo))
                {
                    try
                    {
                        m = XmlDeserializeFromString <Media>(info.FullInfo);
                    }
                    catch (Exception)
                    {
                        info.FullInfo = null;
                    }
                }
                if (string.IsNullOrEmpty(info.FullInfo))
                {
                    try
                    {
                        VideoInfoRepository repo  = new VideoInfoRepository();
                        MediaInfoResult     mInfo = FileHashHelper.GetMediaInfo(v.FullServerPath, true);
                        info.AudioBitrate    = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate;
                        info.AudioCodec      = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec;
                        info.Duration        = mInfo.Duration;
                        info.VideoBitrate    = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate;
                        info.VideoBitDepth   = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth;
                        info.VideoCodec      = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec;
                        info.VideoFrameRate  = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate;
                        info.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution;
                        info.FullInfo        = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo;
                        repo.Save(info);
                        m = XmlDeserializeFromString <Media>(info.FullInfo);
                    }
                    catch (Exception)
                    {
                        //FILE DO NOT EXIST
                    }
                }
            }
            if (m != null)
            {
                m.Id = v.VideoLocalID.ToString();
                List <Stream> subs = SubtitleHelper.GetSubtitleStreams(v.FullServerPath);
                if (subs.Count > 0)
                {
                    m.Parts[0].Streams.AddRange(subs);
                }
                foreach (Part p in m.Parts)
                {
                    p.Id         = null;
                    p.Accessible = "1";
                    p.Exists     = "1";
                    bool vid = false;
                    bool aud = false;
                    bool txt = false;
                    foreach (Stream ss in p.Streams.ToArray())
                    {
                        if ((ss.StreamType == "1") && !vid)
                        {
                            vid = true;
                        }
                        if ((ss.StreamType == "2") && !aud)
                        {
                            aud         = true;
                            ss.Selected = "1";
                        }
                        if ((ss.StreamType == "3") && !txt)
                        {
                            txt         = true;
                            ss.Selected = "1";
                        }
                    }
                }
            }
            return(m);
        }
Ejemplo n.º 16
0
        public bool RefreshMediaInfo()
        {
            try
            {
                logger.Trace($"Getting media info for: {FullServerPath}");

                string name = (ImportFolder.CloudID == null) ? FullServerPath.Replace("/", "\\") : PlexAndKodi.Helper.ReplaceSchemeHost(PlexAndKodi.Helper.ConstructVideoLocalStream(0, VideoLocalID.ToString(), "file", false));

                Media m = MediaConvert.Convert(name, GetFile()); //Mediainfo should have libcurl.dll for http
                if (string.IsNullOrEmpty(m.Duration))
                {
                    m = null;
                }

                if (m != null)
                {
                    VideoLocal info = VideoLocal;
                    info.VideoResolution = (!string.IsNullOrEmpty(m.Width) && !string.IsNullOrEmpty(m.Height))
                        ? m.Width + "x" + m.Height
                        : string.Empty;
                    info.VideoCodec   = (!string.IsNullOrEmpty(m.VideoCodec)) ? m.VideoCodec : string.Empty;
                    info.AudioCodec   = (!string.IsNullOrEmpty(m.AudioCodec)) ? m.AudioCodec : string.Empty;
                    info.Duration     = (!string.IsNullOrEmpty(m.Duration)) ? (long)double.Parse(m.Duration, NumberStyles.Any, CultureInfo.InvariantCulture) : 0;
                    info.VideoBitrate = info.VideoBitDepth = info.VideoFrameRate = info.AudioBitrate = string.Empty;
                    List <JMMContracts.PlexAndKodi.Stream> vparts = m.Parts[0].Streams.Where(a => a.StreamType == "1").ToList();
                    if (vparts.Count > 0)
                    {
                        if (!string.IsNullOrEmpty(vparts[0].Bitrate))
                        {
                            info.VideoBitrate = vparts[0].Bitrate;
                        }
                        if (!string.IsNullOrEmpty(vparts[0].BitDepth))
                        {
                            info.VideoBitDepth = vparts[0].BitDepth;
                        }
                        if (!string.IsNullOrEmpty(vparts[0].FrameRate))
                        {
                            info.VideoFrameRate = vparts[0].FrameRate;
                        }
                    }
                    List <JMMContracts.PlexAndKodi.Stream> aparts = m.Parts[0].Streams.Where(a => a.StreamType == "2").ToList();
                    if (aparts.Count > 0)
                    {
                        if (!string.IsNullOrEmpty(aparts[0].Bitrate))
                        {
                            info.AudioBitrate = aparts[0].Bitrate;
                        }
                    }
                    m.Id = VideoLocalID.ToString();
                    List <JMMContracts.PlexAndKodi.Stream> subs = SubtitleHelper.GetSubtitleStreams(this);
                    if (subs.Count > 0)
                    {
                        m.Parts[0].Streams.AddRange(subs);
                    }
                    foreach (Part p in m.Parts)
                    {
                        p.Id         = null;
                        p.Accessible = "1";
                        p.Exists     = "1";
                        bool vid = false;
                        bool aud = false;
                        bool txt = false;
                        foreach (JMMContracts.PlexAndKodi.Stream ss in p.Streams.ToArray())
                        {
                            if ((ss.StreamType == "1") && !vid)
                            {
                                vid = true;
                            }
                            if ((ss.StreamType == "2") && !aud)
                            {
                                aud         = true;
                                ss.Selected = "1";
                            }
                            if ((ss.StreamType == "3") && !txt)
                            {
                                txt         = true;
                                ss.Selected = "1";
                            }
                        }
                    }
                    info.Media = m;
                    return(true);
                }
                logger.Error($"File {FullServerPath} do not exists, we're unable to read the media information from it");
            }
            catch (Exception e)
            {
                logger.Error($"Unable to read the media information of file {FullServerPath} ERROR: {e}");
            }
            return(false);
        }
Ejemplo n.º 17
0
        public bool RefreshMediaInfo()
        {
            try
            {
                logger.Trace($"Getting media info for: {FullServerPath}");
                Media m = null;
                List <Providers.Azure.Media> webmedias = AzureWebAPI.Get_Media(VideoLocal.ED2KHash);
                if (webmedias != null && webmedias.Count > 0)
                {
                    m = webmedias[0].GetMedia();
                }
                if (m == null)
                {
                    string name = (ImportFolder.CloudID == null)
                        ? FullServerPath.Replace("/", "\\")
                        : PlexAndKodi.Helper.ReplaceSchemeHost(PlexAndKodi.Helper.ConstructVideoLocalStream(0,
                                                                                                            VideoLocalID.ToString(), "file", false));
                    m = MediaConvert.Convert(name, GetFile()); //Mediainfo should have libcurl.dll for http
                    if (string.IsNullOrEmpty(m.Duration))
                    {
                        m = null;
                    }
                    if (m != null)
                    {
                        AzureWebAPI.Send_Media(VideoLocal.ED2KHash, m);
                    }
                }


                if (m != null)
                {
                    VideoLocal info = VideoLocal;
                    FillVideoInfoFromMedia(info, m);

                    m.Id = VideoLocalID.ToString();
                    List <JMMContracts.PlexAndKodi.Stream> subs = SubtitleHelper.GetSubtitleStreams(this);
                    if (subs.Count > 0)
                    {
                        m.Parts[0].Streams.AddRange(subs);
                    }
                    foreach (Part p in m.Parts)
                    {
                        p.Id         = null;
                        p.Accessible = "1";
                        p.Exists     = "1";
                        bool vid = false;
                        bool aud = false;
                        bool txt = false;
                        foreach (JMMContracts.PlexAndKodi.Stream ss in p.Streams.ToArray())
                        {
                            if ((ss.StreamType == "1") && !vid)
                            {
                                vid = true;
                            }
                            if ((ss.StreamType == "2") && !aud)
                            {
                                aud         = true;
                                ss.Selected = "1";
                            }
                            if ((ss.StreamType == "3") && !txt)
                            {
                                txt         = true;
                                ss.Selected = "1";
                            }
                        }
                    }
                    info.Media = m;
                    return(true);
                }
                logger.Error($"File {FullServerPath} does not exist, unable to read media information from it");
            }
            catch (Exception e)
            {
                logger.Error($"Unable to read the media information of file {FullServerPath} ERROR: {e}");
            }
            return(false);
        }
        protected override async Task <TranscodeContext> TranscodeVideoAsync(string clientId, VideoTranscoding video, double timeStart, double timeDuration, bool waitForBuffer)
        {
            FFMpegTranscodeContext context = new FFMpegTranscodeContext(_cacheEnabled, _cachePath);

            context.TargetDuration = video.SourceMediaDuration;
            if (timeStart == 0 && video.TargetIsLive == false && _cacheEnabled)
            {
                timeDuration    = 0;
                context.Partial = false;
            }
            else if (video.TargetVideoContainer == VideoContainer.Hls)
            {
                context.Partial = true;
            }
            else
            {
                video.TargetIsLive = true;
                context.Partial    = true;
            }
            if (video.TargetVideoContainer == VideoContainer.Unknown)
            {
                video.TargetVideoContainer = video.SourceVideoContainer;
            }

            bool          embeddedSupported = false;
            SubtitleCodec embeddedSubCodec  = SubtitleCodec.Unknown;

            if (video.TargetSubtitleSupport == SubtitleSupport.Embedded)
            {
                if (video.TargetVideoContainer == VideoContainer.Matroska)
                {
                    embeddedSupported         = true;
                    embeddedSubCodec          = SubtitleCodec.Ass;
                    video.TargetSubtitleCodec = SubtitleCodec.Ass;
                }
                else if (video.TargetVideoContainer == VideoContainer.Mp4)
                {
                    embeddedSupported         = true;
                    embeddedSubCodec          = SubtitleCodec.MovTxt;
                    video.TargetSubtitleCodec = SubtitleCodec.MovTxt;
                }
                else if (video.TargetVideoContainer == VideoContainer.Hls)
                {
                    embeddedSupported         = true;
                    embeddedSubCodec          = SubtitleCodec.WebVtt;
                    video.TargetSubtitleCodec = SubtitleCodec.WebVtt;
                }
                else if (video.TargetVideoContainer == VideoContainer.Avi)
                {
                    embeddedSupported         = true;
                    embeddedSubCodec          = SubtitleCodec.Srt;
                    video.TargetSubtitleCodec = SubtitleCodec.Srt;
                }
                //else if (video.TargetVideoContainer == VideoContainer.Mpeg2Ts)
                //{
                //  embeddedSupported = true;
                //  embeddedSubCodec = SubtitleCodec.DvbSub;
                //  video.TargetSubtitleCodec = SubtitleCodec.VobSub;
                //}
                else
                {
                    _logger.Debug("FFMpegMediaConverter: Container {0} does not support embedded subtitles", video.TargetVideoContainer);
                }
            }
            video.TargetSubtitleMime       = SubtitleHelper.GetSubtitleMime(video.TargetSubtitleCodec);
            video.PreferredSourceSubtitles = await GetSubtitlesAsync(clientId, video, timeStart).ConfigureAwait(false);

            string transcodingFile = GetTranscodingVideoFileName(video, timeStart, embeddedSupported);

            transcodingFile = Path.Combine(_cachePath, transcodingFile);

            if (File.Exists(transcodingFile))
            {
                //Use non-partial transcode if possible
                TranscodeContext existingContext = await GetExistingTranscodeContextAsync(clientId, video.TranscodeId).ConfigureAwait(false);

                if (existingContext != null)
                {
                    existingContext.TargetFile = transcodingFile;
                    if (existingContext.Stream == null)
                    {
                        existingContext.AssignStream(await GetFileStreamAsync(transcodingFile).ConfigureAwait(false));
                    }
                    if (existingContext.CurrentDuration.TotalSeconds == 0)
                    {
                        double bitrate = 0;
                        if (video.TargetVideoBitrate.HasValue && video.TargetAudioBitrate.HasValue)
                        {
                            bitrate = video.TargetVideoBitrate.Value + video.TargetAudioBitrate.Value;
                        }
                        else if (video.SourceVideoStream.Bitrate.HasValue && video.SourceAudioStreams.Any(a => a.Bitrate > 0))
                        {
                            bitrate = video.SourceVideoStream.Bitrate.Value + video.SourceAudioStreams.Max(a => a.Bitrate ?? 0);
                        }
                        bitrate *= 1024; //Bitrate in bits/s
                        if (bitrate > 0)
                        {
                            long startByte = Convert.ToInt64((bitrate * timeStart) / 8.0);
                            if (existingContext.Stream.Length > startByte)
                            {
                                return(existingContext);
                            }
                        }
                    }
                    else
                    {
                        if (existingContext.CurrentDuration.TotalSeconds > timeStart)
                        {
                            return(existingContext);
                        }
                    }
                }
                else
                {
                    //Presume that it is a cached file
                    TouchFile(transcodingFile);
                    context.Partial    = false;
                    context.TargetFile = transcodingFile;
                    context.AssignStream(await GetFileStreamAsync(transcodingFile).ConfigureAwait(false));
                    return(context);
                }
            }

            if (video.TargetVideoContainer == VideoContainer.Hls)
            {
                long requestedSegmentSequence = requestedSegmentSequence = Convert.ToInt64(timeStart / HLSSegmentTimeInSeconds);
                if (requestedSegmentSequence > 0)
                {
                    requestedSegmentSequence--; //1 segment file margin
                }
                string pathName    = FFMpegPlaylistManifest.GetPlaylistFolderFromTranscodeFile(_cachePath, transcodingFile);
                string playlist    = Path.Combine(pathName, PlaylistManifest.PLAYLIST_MANIFEST_FILE_NAME);
                string segmentFile = Path.Combine(pathName, requestedSegmentSequence.ToString("00000") + ".ts");
                if (File.Exists(playlist) == true && File.Exists(segmentFile) == true)
                {
                    //Use exisitng context if possible
                    TranscodeContext existingContext = await GetExistingTranscodeContextAsync(clientId, video.TranscodeId).ConfigureAwait(false);

                    if (existingContext != null)
                    {
                        if (existingContext.LastSegment > requestedSegmentSequence)
                        {
                            existingContext.TargetFile = playlist;
                            existingContext.SegmentDir = pathName;
                            if (existingContext.Stream == null)
                            {
                                existingContext.AssignStream(await GetFileStreamAsync(playlist).ConfigureAwait(false));
                            }
                            existingContext.HlsBaseUrl = video.HlsBaseUrl;
                            return(existingContext);
                        }
                    }
                    else
                    {
                        //Presume that it is a cached file
                        TouchDirectory(pathName);
                        context.Partial    = false;
                        context.TargetFile = playlist;
                        context.SegmentDir = pathName;
                        context.HlsBaseUrl = video.HlsBaseUrl;
                        context.AssignStream(await GetFileStreamAsync(playlist).ConfigureAwait(false));
                        return(context);
                    }
                }
            }

            FFMpegTranscodeData data = new FFMpegTranscodeData(_cachePath)
            {
                TranscodeId = video.TranscodeId, ClientId = clientId
            };

            if (string.IsNullOrEmpty(video.TranscoderBinPath) == false)
            {
                data.TranscoderBinPath = video.TranscoderBinPath;
            }
            if (string.IsNullOrEmpty(video.TranscoderArguments) == false)
            {
                data.ConcatedFileInput   = video.ConcatSourceMediaPaths;
                data.TranscoderArguments = video.TranscoderArguments;
                data.InputMediaFilePaths = video.SourceMediaPaths;
                if (video.PreferredSourceSubtitles != null)
                {
                    foreach (var mediaSourceIndex in video.PreferredSourceSubtitles.Keys)
                    {
                        foreach (var sub in video.PreferredSourceSubtitles[mediaSourceIndex])
                        {
                            if (string.IsNullOrEmpty(sub.SourcePath) == false)
                            {
                                data.AddSubtitle(mediaSourceIndex, sub.SourcePath);
                                context.TargetSubtitles.Add(sub.SourcePath);
                            }
                        }
                    }
                }
                data.OutputFilePath = transcodingFile;
                context.TargetFile  = transcodingFile;
            }
            else
            {
                data.Encoder = _ffMpegEncoderHandler.StartEncoding(video.TranscodeId, video.TargetVideoCodec);
                _ffMpegCommandline.InitTranscodingParameters(video.ConcatSourceMediaPaths, video.SourceMediaPaths, ref data);

                bool useX26XLib = video.TargetVideoCodec == VideoCodec.H264 || video.TargetVideoCodec == VideoCodec.H265;
                _ffMpegCommandline.AddTranscodingThreadsParameters(!useX26XLib, ref data);

                int subCopyStream = -1;
                if (video.PreferredSourceSubtitles.Any())
                {
                    if (video.FirstPreferredSourceSubtitle.IsEmbedded)
                    {
                        subCopyStream = video.FirstPreferredSourceSubtitle.StreamIndex;
                        _ffMpegCommandline.AddSubtitleCopyParameters(video.FirstPreferredSourceSubtitle, data);
                    }
                    else if (embeddedSupported)
                    {
                        foreach (int mediaSourceIndex in video.PreferredSourceSubtitles.Keys)
                        {
                            _ffMpegCommandline.AddSubtitleEmbeddingParameters(mediaSourceIndex, video.PreferredSourceSubtitles[mediaSourceIndex], embeddedSubCodec, timeStart, data);
                        }
                    }
                    else if (video.TargetSubtitleSupport != SubtitleSupport.SoftCoded)
                    {
                        video.TargetSubtitleSupport = SubtitleSupport.HardCoded; //Fallback to hardcoded subtitles
                        _logger.Debug("FFMpegMediaConverter: Soft subs not supported. Fallback to hardcoded subtitles");
                    }
                }
                else
                {
                    embeddedSupported = false;
                    data.OutputArguments.Add("-sn");
                }

                _ffMpegCommandline.AddTimeParameters(video, timeStart, timeDuration, data);
                _ffMpegCommandline.AddStreamMapParameters(video, data);

                FFMpegEncoderConfig encoderConfig = _ffMpegEncoderHandler.GetEncoderConfig(data.Encoder);
                _ffMpegCommandline.AddVideoParameters(video, data.TranscodeId, encoderConfig, data);
                _ffMpegCommandline.AddVideoAudioParameters(video, data);

                var result = await _ffMpegCommandline.AddTargetVideoFormatAndOutputFileParametersAsync(video, transcodingFile, timeStart, data).ConfigureAwait(false);

                context.TargetFile     = result.TranscodingFile;
                context.CurrentSegment = result.StartSegment;
                if (video.PreferredSourceSubtitles.Any())
                {
                    foreach (var sub in video.PreferredSourceSubtitles.SelectMany(s => s.Value))
                    {
                        if (string.IsNullOrEmpty(sub.SourcePath) == false)
                        {
                            context.TargetSubtitles.Add(sub.SourcePath);
                        }
                    }
                }
            }

            _logger.Info("FFMpegMediaConverter: Invoking transcoder to transcode video file '{0}' for transcode '{1}' with arguments '{2}'", video.SourceMediaPaths.First().Value, video.TranscodeId, String.Join(", ", data.OutputArguments.ToArray()));
            context.Start();
            context.AssignStream(await ExecuteTranscodingProcessAsync(data, context, waitForBuffer).ConfigureAwait(false));
            return(context);
        }