Exemple #1
0
        /// <summary>
        /// Handle eac3 conversions for mencoder
        /// TODO: This function is redundant and incorrectly written, handbrake, ffmpeg and mencoder are able to handle eac3 audio why do we need this?
        /// </summary>
        private bool ConvertMencoderEAC3()
        {
            string audioStream = "";

            _jobStatus.PercentageComplete = 100; //all good by default
            _jobStatus.ETA = "";

            if ((_videoFile.AudioCodec != "e-ac-3") && (_videoFile.AudioCodec != "eac3"))
                return true;
            
            // Only supports MP4, MKV and AVI
            if ((_extension != ".mp4") && (_extension != ".mkv") && (_extension != ".avi"))
                return true;

            _jobStatus.CurrentAction = Localise.GetPhrase("Converting E-AC3");
            _jobLog.WriteEntry(this, ("Converting E-AC3"), Log.LogEntryType.Information);

            // Convert EAC3 file
            string eac3toParams;
            string audiop = _audioParams.Trim();
            if (audiop.Contains("faac") || audiop.Contains("libfaac") || audiop.Contains("aac"))
            {
                audioStream = Path.Combine(_workingPath, Path.GetFileNameWithoutExtension(SourceVideo) + "_AUDIO.mp4");
                eac3toParams = Util.FilePaths.FixSpaces(SourceVideo) + " " + Util.FilePaths.FixSpaces(audioStream) + " -384";
            }
            else // TODO: what about other audio formats?
            {
                audioStream = Path.Combine(_workingPath, Path.GetFileNameWithoutExtension(SourceVideo) + "_AUDIO.ac3");
                eac3toParams = Util.FilePaths.FixSpaces(SourceVideo) + " " + Util.FilePaths.FixSpaces(audioStream) + " -384";
            }

            FileIO.TryFileDelete(audioStream); // Clean before starting
            Eac3To eac3to = new AppWrapper.Eac3To(eac3toParams, _jobStatus, _jobLog);
            eac3to.Run();
            if (!eac3to.Success)
            {
                FileIO.TryFileDelete(audioStream); // Clean
                _jobLog.WriteEntry(this, ("E-AC3 conversion unsuccessful"), Log.LogEntryType.Error);
                _jobStatus.ErrorMsg = "E-AC3 conversion unsuccessful";
                _jobStatus.PercentageComplete = 0;
                return false; // something went wrong
            }

            // Mux into destination 
            if ((_extension == ".mp4") || (_extension == ".m4v"))
            {
                _jobLog.WriteEntry(this, ("Muxing E-AC3 using MP4Box"), Log.LogEntryType.Information);
                string mp4boxParams = " -keep-sys -keep-all -add " + FilePaths.FixSpaces(audioStream) + " " + FilePaths.FixSpaces(_convertedFile);
                _jobStatus.PercentageComplete = 0; //reset
                _jobStatus.ETA = "";
                MP4Box mp4box = new MP4Box(mp4boxParams, _jobStatus, _jobLog);
                mp4box.Run();
                if (!mp4box.Success || _jobStatus.PercentageComplete < GlobalDefs.ACCEPTABLE_COMPLETION) // check for incomplete output or process issues
                {
                    FileIO.TryFileDelete(audioStream);
                    _jobLog.WriteEntry(this, ("E-AC3 muxing using MP4Box failed at") + " " + _jobStatus.PercentageComplete.ToString(System.Globalization.CultureInfo.InvariantCulture), Log.LogEntryType.Error);
                    _jobStatus.ErrorMsg = "E-AC3 muxing using MP4Box failed";
                    _jobStatus.PercentageComplete = 0; // something went wrong with the process
                    return false;
                }
            }
            else if (_extension == ".mkv")
            {
                _jobLog.WriteEntry(this, ("Muxing E-AC3 using MKVMerge"), Log.LogEntryType.Information);
                string remuxedFile = Path.Combine(_workingPath, Path.GetFileNameWithoutExtension(_convertedFile) + "_REMUX.mkv");
                FileIO.TryFileDelete(remuxedFile);
                string mkvmergeParams = "--clusters-in-meta-seek --compression -1:none " + FilePaths.FixSpaces(_convertedFile) + " --compression -1:none " + FilePaths.FixSpaces(audioStream) + " -o " + FilePaths.FixSpaces(remuxedFile);
                _jobStatus.PercentageComplete = 0; //reset
                _jobStatus.ETA = "";
                MKVMerge mkvmerge = new MKVMerge(mkvmergeParams, _jobStatus, _jobLog);
                mkvmerge.Run();
                if (!mkvmerge.Success)
                {
                    FileIO.TryFileDelete(audioStream);
                    FileIO.TryFileDelete(remuxedFile);
                    _jobLog.WriteEntry(this, ("Muxing E-AC3 using MKVMerge failed"), Log.LogEntryType.Error);
                    _jobStatus.ErrorMsg = "Muxing E-AC3 using MKVMerge failed";
                    _jobStatus.PercentageComplete = 0; // something went wrong with the process
                    return false;
                }

                try
                {
                    _jobLog.WriteEntry(this, ("Moving MKVMerge muxed E-AC3"), Log.LogEntryType.Information);
                    FileIO.TryFileDelete(_convertedFile);
                    File.Move(remuxedFile, _convertedFile);
                    _jobStatus.PercentageComplete = 100; //proxy for job done since mkvmerge doesn't report
                    _jobStatus.ETA = "";
                }
                catch (Exception e)
                {
                    FileIO.TryFileDelete(audioStream);
                    FileIO.TryFileDelete(remuxedFile);
                    _jobLog.WriteEntry(this, ("Unable to move MKVMerge remuxed E-AC3 file") + " " + remuxedFile + "\r\nError : " + e.ToString(), Log.LogEntryType.Error);
                    _jobStatus.PercentageComplete = 0;
                    _jobStatus.ErrorMsg = "Unable to move MKVMerge remuxed E-AC3 file";
                    return false;
                }
            }
            else
            {
                _jobStatus.PercentageComplete = 0; //reset
                _jobStatus.ETA = "";
                _jobLog.WriteEntry(this, ("Muxing E-AC3 using FFMPEGRemux"), Log.LogEntryType.Information);
                double fps = 0;
                double.TryParse(_fps, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out fps);
                RemuxExt remuxFile = new RemuxExt(_convertedFile, _workingPath, (fps <= 0 ? _videoFile.Fps : fps), _jobStatus, _jobLog, _remuxTo); // Use output FPS if it exists otherwise the source file FPS (since it has not changed)
                if (remuxFile.FfmpegRemux(audioStream))
                {
                    _convertedFile = remuxFile.RemuxedFile;
                }
                else
                {
                    FileIO.TryFileDelete(audioStream);
                    _jobLog.WriteEntry(this, ("Error Muxing E-AC3 using FFMPEGRemux"), Log.LogEntryType.Error);
                    _jobStatus.PercentageComplete = 0;
                    _jobStatus.ErrorMsg = "Error Muxing E-AC3 using FFMPEGRemux";
                    return false;
                }
            }

            FileIO.TryFileDelete(audioStream); // Clean up
            _jobLog.WriteEntry(this, ("Finished EAC3 conversion, file size [KB]") + " " + (FileIO.FileSize(_convertedFile) / 1024).ToString("N", System.Globalization.CultureInfo.InvariantCulture), Log.LogEntryType.Debug);

            return true;
        }
Exemple #2
0
        /// <summary>
        /// Adds the subtitle file and chapters to the target file
        /// </summary>
        /// <param name="srtFile">Path to subtitle file</param>
        /// <param name="neroChapterFile">Path to Nero chapter file</param>
        /// <param name="xmlChapterFile">Path to xml (iTunes) chapter file</param>
        /// <param name="targetFile">Path to target file</param>
        /// <returns>False in case of an error</returns>
        public bool AddSubtitlesAndChaptersToFile(string srtFile, string neroChapterFile, string xmlChapterFile, string targetFile)
        {
            _jobLog.WriteEntry("Subtitle File : " + srtFile + "\nChapter File : " + neroChapterFile + "\nTarget File : " + targetFile, Log.LogEntryType.Debug);

            if (!File.Exists(targetFile))
                return false;

            if (String.IsNullOrWhiteSpace(xmlChapterFile) && String.IsNullOrWhiteSpace(neroChapterFile) && String.IsNullOrWhiteSpace(srtFile)) // Atleast one file should be there to proceeed
                return true; // nothing to do

            if ((FileIO.FileSize(xmlChapterFile) <= 0) && (FileIO.FileSize(neroChapterFile) <= 0) && (FileIO.FileSize(srtFile) < 0)) // Atleast one file should be valid to proceeed
                return true; // nothing to do

            string parameters = "";
            switch (FilePaths.CleanExt(targetFile))
            {
                case ".mp4":
                case ".m4v":
                    if (File.Exists(srtFile)) // Add the subtitles
                        parameters += " -add " + Util.FilePaths.FixSpaces(srtFile) + ":hdlr=sbtl";

                    if (File.Exists(neroChapterFile)) // Add the nero chapters
                        parameters += " -chap " + Util.FilePaths.FixSpaces(neroChapterFile);

                    if (File.Exists(xmlChapterFile)) // Add the iTunes chapters TODO: adding ttxt chapter files leads to incorrect file length (minutes) reported, why is MP4Box doing this? Is the TTXT format incorrect?
                        parameters += " -add " + Util.FilePaths.FixSpaces(xmlChapterFile) + ":chap";

                    parameters += " " + Util.FilePaths.FixSpaces(targetFile); // output file

                    MP4Box mp4Box = new MP4Box(parameters, _jobStatus, _jobLog, _ignoreSuspend);
                    mp4Box.Run();
                    if (!mp4Box.Success || (FileIO.FileSize(targetFile) <= 0))
                    {
                        _jobStatus.PercentageComplete = 0;
                        _jobStatus.ErrorMsg = "Mp4Box adding subtitles failed";
                        _jobLog.WriteEntry(Localise.GetPhrase("Mp4Box adding subtitles failed"), Log.LogEntryType.Error); ;
                        return false;
                    }

                    return true; // all done

                case ".mkv":
                    string outputFile = FilePaths.GetFullPathWithoutExtension(targetFile) + "-temp.mkv";
                    parameters += "--clusters-in-meta-seek -o " + Util.FilePaths.FixSpaces(outputFile) + " --compression -1:none " + Util.FilePaths.FixSpaces(targetFile); // output file

                    if (File.Exists(srtFile)) // Add the subtitles
                        parameters += " --compression -1:none " + Util.FilePaths.FixSpaces(srtFile);

                    if (File.Exists(neroChapterFile)) // Add the chapters
                        parameters += " --compression -1:none --chapters " + Util.FilePaths.FixSpaces(neroChapterFile);

                    MKVMerge mkvMerge = new MKVMerge(parameters, _jobStatus, _jobLog, _ignoreSuspend);
                    mkvMerge.Run();
                    if (!mkvMerge.Success || (Util.FileIO.FileSize(outputFile) <= 0)) // check for +ve success
                    {
                        _jobStatus.PercentageComplete = 0;
                        _jobStatus.ErrorMsg = "MKVMerge adding subtitles failed";
                        _jobLog.WriteEntry(Localise.GetPhrase("MKVMerge adding subtitles failed"), Log.LogEntryType.Error); ;
                        return false;
                    }

                    // Replace the temp file
                    Util.FileIO.TryFileReplace(targetFile, outputFile);

                    if (Util.FileIO.FileSize(targetFile) <= 0)
                    {
                        _jobLog.WriteEntry(Localise.GetPhrase("MKVMerge: Error moving files"), Log.LogEntryType.Error); ;
                        return false; // Something went wrong
                    }

                    return true; // done

                default:
                    return true; // not a valid type, so ignore it
            }
        }
Exemple #3
0
        private bool MP4BoxRemux()
        {
            _jobStatus.ErrorMsg = "";
            _jobStatus.PercentageComplete = 100; //all good to start with
            _jobStatus.ETA = "";

            Util.FileIO.TryFileDelete(RemuxedTempFile);
            string Parameters = " -keep-sys -keep-all";

            //Check for Null FPS (bug with MediaInfo for some .TS files)
            if (_fps <= 0)
            {
                _jobLog.WriteEntry(this, Localise.GetPhrase("Mp4BoxRemuxAVI FPS 0 reported by video file - non compliant video file, skipping adding to parameter"), Log.LogEntryType.Warning);
                Parameters += " -add " + FilePaths.FixSpaces(_originalFile) +
                              " -new " + FilePaths.FixSpaces(RemuxedTempFile);
            }
            else
            {
                Parameters += " -fps " + _fps.ToString(System.Globalization.CultureInfo.InvariantCulture) +
                              " -add " + FilePaths.FixSpaces(_originalFile) +
                              " -new " + FilePaths.FixSpaces(RemuxedTempFile);
            }

            MP4Box mp4Box = new MP4Box(Parameters, _jobStatus, _jobLog);
            mp4Box.Run();
            if (!mp4Box.Success || _jobStatus.PercentageComplete < GlobalDefs.ACCEPTABLE_COMPLETION)
            {
                _jobLog.WriteEntry(this, Localise.GetPhrase("MP4BoxRemux failed"), Log.LogEntryType.Error);
                _jobStatus.ErrorMsg = Localise.GetPhrase("MP4BoxRemux failed");
                return false;
            }

            _jobLog.WriteEntry(this, Localise.GetPhrase("MP4Box remux moving file"), Log.LogEntryType.Information);
            return ReplaceTempRemuxed();
        }
Exemple #4
0
        private bool MP4BoxRemuxAvi()
        {
            _jobStatus.ErrorMsg = "";
            _jobStatus.PercentageComplete = 100; //all good to start with
            _jobStatus.ETA = "";

            string fileNameBase = Path.Combine(_workingPath, Path.GetFileNameWithoutExtension(_originalFile));
            string audioStream = fileNameBase + "_audio.raw";
            string newAudioStream = fileNameBase + "_audio.aac";
            string videoStream = fileNameBase + "_video.h264";

            Util.FileIO.TryFileDelete(RemuxedTempFile);

            // Video
            string Parameters = " -keep-sys -aviraw video -out " + FilePaths.FixSpaces(videoStream) + " " + FilePaths.FixSpaces(_originalFile);

            _jobStatus.CurrentAction = Localise.GetPhrase("Remuxing to") + " " + _remuxTo.ToLower() + " " + Localise.GetPhrase("Part") + " 1";

            MP4Box mp4Box = new MP4Box(Parameters, _jobStatus, _jobLog);
            mp4Box.Run();
            if (!mp4Box.Success || _jobStatus.PercentageComplete < GlobalDefs.ACCEPTABLE_COMPLETION) // check for completion of job
            {
                _jobStatus.ErrorMsg = "MP4Box Remux Video AVI failed";
                _jobLog.WriteEntry(this, _jobStatus.ErrorMsg + " at " + _jobStatus.PercentageComplete.ToString(System.Globalization.CultureInfo.InvariantCulture), Log.LogEntryType.Error);
                return false;
            }

            // Audio
            Parameters = " -keep-all -keep-sys -aviraw audio -out " + FilePaths.FixSpaces(audioStream) + " " + FilePaths.FixSpaces(_originalFile);

            _jobStatus.CurrentAction = Localise.GetPhrase("Remuxing to") + " " + _remuxTo.ToLower() + " " + Localise.GetPhrase("Part") + " 2";

            mp4Box = new MP4Box(Parameters, _jobStatus, _jobLog);
            mp4Box.Run();
            if (!mp4Box.Success || _jobStatus.PercentageComplete < GlobalDefs.ACCEPTABLE_COMPLETION) //check for completion of job
            {
                _jobStatus.ErrorMsg = "MP4Box Remux Audio AVI failed";
                _jobLog.WriteEntry(this, _jobStatus.ErrorMsg + " at " + _jobStatus.PercentageComplete.ToString(System.Globalization.CultureInfo.InvariantCulture), Log.LogEntryType.Error);
                return false;
            }

            // Check if streams are extracted
            if ((File.Exists(audioStream)) && (File.Exists(videoStream)))
            {
                _jobLog.WriteEntry(this, Localise.GetPhrase("MP4Box remux avi moving file"), Log.LogEntryType.Information);
                try
                {
                    Util.FileIO.TryFileDelete(newAudioStream);
                    File.Move(audioStream, newAudioStream);
                }
                catch (Exception e)
                {
                    _jobLog.WriteEntry(this, Localise.GetPhrase("Unable to move remuxed stream") + " " + audioStream + " to " + newAudioStream + "\r\nError : " + e.ToString(), Log.LogEntryType.Error);
                    _jobStatus.PercentageComplete = 0;
                    _jobStatus.ErrorMsg = "Unable to move muxed stream";
                    return false;
                }

                string mergeParameters = " -keep-sys -keep-all";

                //Check for Null FPS (bug with MediaInfo for some .TS files)
                if (_fps <= 0)
                {
                    _jobLog.WriteEntry(this, Localise.GetPhrase("Mp4BoxRemuxAVI FPS 0 reported by video file - non compliant video file, skipping adding to parameter"), Log.LogEntryType.Warning);
                    mergeParameters += " -add " + FilePaths.FixSpaces(videoStream) +
                                       " -add " + FilePaths.FixSpaces(newAudioStream) +
                                       " -new " + FilePaths.FixSpaces(RemuxedTempFile);
                }
                else
                {
                    mergeParameters += " -fps " + _fps.ToString(System.Globalization.CultureInfo.InvariantCulture) +
                                       " -add " + FilePaths.FixSpaces(videoStream) +
                                       " -add " + FilePaths.FixSpaces(newAudioStream) +
                                       " -new " + FilePaths.FixSpaces(RemuxedTempFile);
                }


                _jobStatus.CurrentAction = Localise.GetPhrase("Remuxing to") + " " + _remuxTo.ToLower() + " " + Localise.GetPhrase("Part") + " 3";

                mp4Box = new MP4Box(mergeParameters, _jobStatus, _jobLog);
                mp4Box.Run();
                if (!mp4Box.Success || _jobStatus.PercentageComplete < GlobalDefs.ACCEPTABLE_COMPLETION) // check for completion
                {
                    _jobStatus.ErrorMsg = "Mp4Box Remux Merger AVI with FPS conversion failed";
                    _jobLog.WriteEntry(this, _jobStatus.ErrorMsg, Log.LogEntryType.Error);
                    return false;
                }

                Util.FileIO.TryFileDelete(videoStream);
                Util.FileIO.TryFileDelete(newAudioStream);

                _jobLog.WriteEntry(this, Localise.GetPhrase("MP4Box remux AVI trying to move remuxed file"), Log.LogEntryType.Information);
                return ReplaceTempRemuxed();
            }
            else
            {
                _jobLog.WriteEntry(this, Localise.GetPhrase("MP4Box Remux AVI of") + " " + _originalFile + " " + Localise.GetPhrase("failed.  Extracted video and audio streams not found."), Log.LogEntryType.Error);
                _jobStatus.PercentageComplete = 0;
                _jobStatus.ErrorMsg = "Remux failed, extracted video streams not found";
                return false;
            }
        }
Exemple #5
0
        /// <summary>
        /// Remove commercials from MP4 files using MP4Box
        /// </summary>
        private void CutMP4()
        {
            List<KeyValuePair<float, float>> keepList = new List<KeyValuePair<float, float>>();

            // Read the EDL file and convert into MP4Box cut structure
            if (!ParseEDLFile(ref keepList))
                return;

            // Create the MP4 splits
            //Setup the 'look for splits' variables
            string searchPattern = Path.GetFileNameWithoutExtension(_uncutVideo) + "*" + _ext;
            string searchPath = _workingPath;
            List<string> filesFound = new List<string>();
            filesFound.Add(_uncutVideo);

            //Do the cuts and pick them up as we go
            int cutNumber = 0;
            string mergeParams = "";
            foreach (KeyValuePair<float, float> keep in keepList)
            {
                _jobStatus.CurrentAction = Localise.GetPhrase("Cutting commercials from video - segment") + " " + cutNumber.ToString(CultureInfo.InvariantCulture);
                _jobLog.WriteEntry(this, Localise.GetPhrase("MP4Box: Cutting commercials from video - segment ") + cutNumber.ToString(CultureInfo.InvariantCulture), Log.LogEntryType.Information);
                string cutFileName = CutFileName(_uncutVideo, keep.Key, keep.Value);
                string Parameters = " -keep-all -keep-sys -splitx " + keep.Key.ToString(CultureInfo.InvariantCulture) + ":" + keep.Value.ToString(CultureInfo.InvariantCulture) + " -out " + Util.FilePaths.FixSpaces(cutFileName) + " " + Util.FilePaths.FixSpaces(_uncutVideo);
                MP4Box mp4Box = new MP4Box(Parameters, _jobStatus, _jobLog);
                mp4Box.Run();
                if (!mp4Box.Success) // Don't check for % here since Comskip has a bug that gives EDL cut segments past the end of the file || _jobStatus.PercentageComplete < GlobObjects.ACCEPTABLE_COMPLETION) // each run resets this number or an error in the process
                {
                    _jobStatus.PercentageComplete = 0;
                    _jobStatus.ErrorMsg = "Mp4Box splitting video segments failed";
                    _jobLog.WriteEntry(this, Localise.GetPhrase("Mp4Box splitting video segments failed"), Log.LogEntryType.Error); ;
                    return;
                }


                //Setup the directory search - do not use Enumerate files since it's lazy in updating and skips files
                IEnumerable<string> newFilesFound = new List<string>();
                try
                {
                    newFilesFound = Directory.GetFiles(searchPath, searchPattern).OrderBy(File.GetCreationTime); //put them back in the order they were split
                }
                catch (Exception e)
                {
                    _jobStatus.ErrorMsg = "MP4 Commercial cut failed trying to get list of file segments";
                    _jobLog.WriteEntry(this, Localise.GetPhrase("MP4 Commercial cut failed trying to get list of file segments") + "\r\nError : " + e.ToString(), Log.LogEntryType.Error);
                    _jobStatus.PercentageComplete = 0;
                    return;
                }

                //Look for the split name as it cannot be specified before mp4box execution
                foreach (string f in newFilesFound)
                {
                    if (!filesFound.Contains(f))
                    {
                        // Build the merge cmd
                        if (cutNumber == 0)
                            mergeParams += " -keep-all -keep-sys";

                        mergeParams += " -cat " + Util.FilePaths.FixSpaces(f);
                        cutNumber++;
                        filesFound.Add(f);
                        _jobLog.WriteEntry(this, Localise.GetPhrase("MP4Box: Found a new segment to merge"), Log.LogEntryType.Information);
                        _jobLog.WriteEntry(this, "No : " + cutNumber.ToString(CultureInfo.InvariantCulture) + " Filename : " + f, Log.LogEntryType.Debug);
                    }
                }
            }

            if (cutNumber < 1)
            {
                _jobLog.WriteEntry(this, Localise.GetPhrase("No commercials to remove from ") + EDLFile, Log.LogEntryType.Information);
                _jobStatus.PercentageComplete = 100; //Set to success since sometime mp4box doesn't set to 100 if there no/incomplete pieces to strip
                return;
            }

            // Merge the splits
            string tempFile = CutFileName(_uncutVideo, 0, 0);

            mergeParams += " -new " + Util.FilePaths.FixSpaces(tempFile);
            
            _jobStatus.CurrentAction = Localise.GetPhrase("Merging commercial free segments into new video");
            _jobLog.WriteEntry(this, Localise.GetPhrase("MP4Box: Merging commercial free segments into new video"), Log.LogEntryType.Information);

            MP4Box mp4BoxMerge = new MP4Box(mergeParams, _jobStatus, _jobLog);
            mp4BoxMerge.Run();
            if (!mp4BoxMerge.Success || _jobStatus.PercentageComplete < GlobalDefs.ACCEPTABLE_COMPLETION || (Util.FileIO.FileSize(tempFile) <= 0)) // each run resets this number or an error in the procecss
            {
                CleanupCutFiles(filesFound); //Clean up cut files
                _jobStatus.PercentageComplete = 0;
                _jobStatus.ErrorMsg = "MP4Box merging video segments failed";
                _jobLog.WriteEntry(this, Localise.GetPhrase("MP4Box merging video segments failed"), Log.LogEntryType.Error); ;
                return;
            }


            // Move the files
            _jobLog.WriteEntry(this, Localise.GetPhrase("MP4Box trying to replace file") + " Output : " + _uncutVideo + " Temp : " + tempFile, Log.LogEntryType.Debug);
            RenameAndMoveFile(tempFile);

            //Clean up cut files
            CleanupCutFiles(filesFound);
        }