private void saveEDLCmd_Click(object sender, RoutedEventArgs e) { System.Windows.Forms.SaveFileDialog edlFile = new System.Windows.Forms.SaveFileDialog(); edlFile.InitialDirectory = System.IO.Path.GetDirectoryName(mediaPlayer.Source.LocalPath); edlFile.FileName = FilePaths.GetFullPathWithoutExtension(mediaPlayer.Source.LocalPath) + ".edl"; // Default filename is same as original filename edlFile.DefaultExt = "*.edl"; edlFile.AddExtension = true; edlFile.Filter = "EDL files|*.edl|All files|*.*"; if (edlFile.ShowDialog() == System.Windows.Forms.DialogResult.OK) { WriteEDL(edlFile.FileName); } }
private void mediaPlayer_MediaOpened(object sender, RoutedEventArgs e) { ResetMediaOpenButton(); if (!mediaPlayer.NaturalDuration.HasTimeSpan) { MessageBox.Show(Localise.GetPhrase("Failed to read media duration"), Localise.GetPhrase("Media Read Error"), MessageBoxButton.OK, MessageBoxImage.Error); return; } _totalVideoTime = mediaPlayer.NaturalDuration.TimeSpan; // Total video time timeSlider.Maximum = _totalVideoTime.TotalMilliseconds; // Set the slider max value // NOTE: Update the timeStamp - don't fire event (simulate button) since it sets the mediaplayer to mode to manual and it fails to show the first frame of the video RoutedPropertyChangedEventArgs <double> newEventArgs = new RoutedPropertyChangedEventArgs <double>(1, 0); timeSlider_ValueChanged(sender, newEventArgs); // Enable button in the end after setting everything if (!_playing) { playStopCmd.IsEnabled = timeSlider.IsEnabled = cutStartCmd.IsEnabled = true; cutEndCmd.IsEnabled = false; mediaPlayer.LoadedBehavior = MediaState.Manual; // Set to manual and pause it so that the seek function works (otherwise it needs to be manually played for seek to work) mediaPlayer.Pause(); // Load and pause the video } // Load the EDL file if found if (edlCuts.Items.Count <= 0) // MediaOpened is called multiple times sometimes, only load it once { string edlFile = FilePaths.GetFullPathWithoutExtension(mediaPlayer.Source.LocalPath) + ".edl"; string vprjFile = FilePaths.GetFullPathWithoutExtension(mediaPlayer.Source.LocalPath) + ".vprj"; if (FileIO.FileSize(edlFile) > 0) // Check if it exists { ReadEDL(edlFile); } else if (FileIO.FileSize(vprjFile) > 0) // Check for VPRJ file { if (EDL.ConvertVPRJtoEDL(vprjFile, edlFile, new Log())) // Convert to EDL { if (FileIO.FileSize(edlFile) > 0) { ReadEDL(edlFile); } } } } }
/// <summary> /// Extracts subtitles from a video file into a SRT format (with same name) and cleans it up. /// It will overwrite any existing SRT files /// If there are multiple subtitles it extracts them into multiple files with incremental names. /// </summary> /// <param name="sourceFile">Path to video file</param> /// <param name="offset">Offset of the subtitles during extraction</param> /// <param name="overWrite">True to overwrite existing SRT files, false to create new ones with incremental names</param> /// <param name="languageExtractList">List of 3 digit language codes to extract (blank to extract all, unnamed languages will always be extracted)</param> /// <returns>True if successful</returns> public bool ExtractSubtitles(string sourceFile, string workingPath, int startTrim, int endTrim, double offset, bool overWrite, List <string> languageExtractList) { _jobLog.WriteEntry(this, ("Extracting Subtitles from " + sourceFile + " into SRT file"), Log.LogEntryType.Information); _jobLog.WriteEntry(this, "Source File : " + sourceFile, Log.LogEntryType.Debug); _jobLog.WriteEntry(this, "Working Path " + workingPath, Log.LogEntryType.Debug); _jobLog.WriteEntry(this, "Start Trim : " + startTrim.ToString(CultureInfo.InvariantCulture), Log.LogEntryType.Debug); _jobLog.WriteEntry(this, "Stop Trim : " + endTrim.ToString(CultureInfo.InvariantCulture), Log.LogEntryType.Debug); _jobLog.WriteEntry(this, "Offset : " + offset.ToString(CultureInfo.InvariantCulture), Log.LogEntryType.Debug); if (String.IsNullOrEmpty(sourceFile)) { return(true); // nothing to do } if (!File.Exists(sourceFile)) { _jobLog.WriteEntry(this, ("File does not exist " + sourceFile), Log.LogEntryType.Warning); return(true); //nothing to process } FFmpegMediaInfo mediaInfo = new FFmpegMediaInfo(sourceFile, _jobStatus, _jobLog); if (!mediaInfo.Success || mediaInfo.ParseError) { _jobLog.WriteEntry(this, ("Error reading subtitle info from file"), Log.LogEntryType.Error); return(false); } _jobLog.WriteEntry(this, "Found " + mediaInfo.SubtitleTracks.ToString() + " Subtitle tracks, extract only the first matching track", Log.LogEntryType.Debug); bool extractedSubtitle = false; for (int i = 0; i < mediaInfo.SubtitleTracks; i++) { if (extractedSubtitle) // Only extract and use one subtitle (sometimes chapter tracks are misidentified as subtitle tracks) { continue; } // Build the command line string parameters = ""; string outputSRTFile = ""; // Using Serviio subtitle filename format (filename.srt or filename_language.srt or filename_uniquenumber.srt) // Check for language comparison if required if (languageExtractList != null) { if (languageExtractList.Count > 0) // If list is empty, we extract all { _jobLog.WriteEntry(this, "Subtitle language extraction list -> " + String.Join(",", languageExtractList.ToArray()), Log.LogEntryType.Debug); if (!String.IsNullOrWhiteSpace(mediaInfo.MediaInfo.SubtitleInfo[i].Language)) // check if we have a language defined for this track { if (!languageExtractList.Contains(mediaInfo.MediaInfo.SubtitleInfo[i].Language)) // This language is not in the list of extraction { _jobLog.WriteEntry(this, "Skipping subtitle extraction since subtitle language >" + mediaInfo.MediaInfo.SubtitleInfo[i].Language + "< is NOT in the subtitle language list", Log.LogEntryType.Warning); continue; // Skip this subtitle track } } else { _jobLog.WriteEntry(this, "Extracting subtitle since there is no language defined for track", Log.LogEntryType.Debug); } } } // Check for existing SRT files if (overWrite) { outputSRTFile = Path.Combine(workingPath, Path.GetFileNameWithoutExtension(sourceFile)) + (i > 0 ? (String.IsNullOrWhiteSpace(mediaInfo.MediaInfo.SubtitleInfo[i].Language) ? "_" + i.ToString() : "_" + mediaInfo.MediaInfo.SubtitleInfo[i].Language) : "") + ".srt"; // First file user default name, then try to name with language first, if not give a unique number parameters += " -y"; } else // Create a unique SRT file name { int existingSRTCount = 0; outputSRTFile = Path.Combine(workingPath, Path.GetFileNameWithoutExtension(sourceFile)) + ".srt"; // Try default name while (File.Exists(outputSRTFile)) { _jobLog.WriteEntry(this, "Subtitle file " + outputSRTFile + " exists, creating a new unique SRT filename", Log.LogEntryType.Debug); outputSRTFile = Path.Combine(workingPath, Path.GetFileNameWithoutExtension(sourceFile)) + (String.IsNullOrWhiteSpace(mediaInfo.MediaInfo.SubtitleInfo[i].Language) ? "_" + existingSRTCount.ToString() : "_" + mediaInfo.MediaInfo.SubtitleInfo[i].Language + (existingSRTCount > 0 ? existingSRTCount.ToString() : "")) + ".srt"; // Create a unique SRT filename, try with language first, if not give a unique identifier, avoid a loop existingSRTCount++; } } // Build ffmpeg command line parameters += " -i " + FilePaths.FixSpaces(sourceFile); parameters += " -an -vn"; parameters += " -map 0:" + mediaInfo.MediaInfo.SubtitleInfo[i].Stream.ToString(); // Subtitle steam no parameters += " -scodec copy -copyinkf -f srt " + FilePaths.FixSpaces(outputSRTFile); // Now extract it _jobLog.WriteEntry(this, "Extracting Subtitle " + (i + 1).ToString() + " with language >" + mediaInfo.MediaInfo.SubtitleInfo[i].Language + "< to " + outputSRTFile, Log.LogEntryType.Debug); FFmpeg ffmpeg = new FFmpeg(parameters, _jobStatus, _jobLog); ffmpeg.Run(); if (!ffmpeg.Success) { FileIO.TryFileDelete(outputSRTFile); // Delete partial file // Backup, try using MP4Box instead to extract it _jobLog.WriteEntry(this, ("FFMPEG failed to extract subtitles into SRT file, retrying using MP4Box"), Log.LogEntryType.Warning); parameters = "-srt " + (mediaInfo.MediaInfo.SubtitleInfo[i].Stream + 1).ToString() + " " + FilePaths.FixSpaces(sourceFile); // MP4Box create an output file called <input>_<track>_text.srt // Check if the output srt exists and then rename it if it does string tempSrtOutput = FilePaths.GetFullPathWithoutExtension(sourceFile) + "_" + (mediaInfo.MediaInfo.SubtitleInfo[i].Stream + 1).ToString() + "_text.srt"; bool tempSrtExists = false; if (File.Exists(tempSrtOutput)) // Save the output srt filename if it exists { try { FileIO.MoveAndInheritPermissions(tempSrtOutput, tempSrtOutput + ".tmp"); } catch (Exception e) { _jobLog.WriteEntry(this, ("Error extracting subtitles into SRT file.\r\n" + e.ToString()), Log.LogEntryType.Error); return(false); } tempSrtExists = true; } // Extract the subtitle MP4Box mp4Box = new MP4Box(parameters, _jobStatus, _jobLog); mp4Box.Run(); if (!mp4Box.Success) { _jobLog.WriteEntry(this, ("Error extracting subtitles into SRT file"), Log.LogEntryType.Error); FileIO.TryFileDelete(tempSrtOutput); // Delete partial file if (tempSrtExists) { RestoreSavedSrt(tempSrtOutput); } return(false); } if (FileIO.FileSize(tempSrtOutput) <= 0) // MP4Box always return success even if nothing is extracted, so check if has been extracted { _jobLog.WriteEntry(this, "No or empty Subtitle file " + tempSrtOutput + " extracted by MP4Box, skipping", Log.LogEntryType.Debug); FileIO.TryFileDelete(tempSrtOutput); // Delete empty file } else { // Rename the temp output SRT to the expected name try { FileIO.MoveAndInheritPermissions(tempSrtOutput, outputSRTFile); } catch (Exception e) { _jobLog.WriteEntry(this, ("Error extracting subtitles into SRT file.\r\n" + e.ToString()), Log.LogEntryType.Error); FileIO.TryFileDelete(tempSrtOutput); // Delete partial file if (tempSrtExists) { RestoreSavedSrt(tempSrtOutput); } return(false); } } // Restore temp SRT file if it exists if (tempSrtExists) { RestoreSavedSrt(tempSrtOutput); } } if (FileIO.FileSize(outputSRTFile) <= 0) // Check for empty files { _jobLog.WriteEntry(this, "Empty Subtitle file " + outputSRTFile + " extracted, deleting it", Log.LogEntryType.Warning); FileIO.TryFileDelete(outputSRTFile); // Delete empty file } else { // Trim the SRT file if required if (startTrim > 0 || endTrim > 0) { // Get the length of the video, needed to calculate end point float Duration = 0; Duration = VideoParams.VideoDuration(sourceFile); if (Duration <= 0) { FFmpegMediaInfo ffmpegStreamInfo = new FFmpegMediaInfo(sourceFile, _jobStatus, _jobLog); if (ffmpegStreamInfo.Success && !ffmpegStreamInfo.ParseError) { // Converted file should contain only 1 audio stream Duration = ffmpegStreamInfo.MediaInfo.VideoInfo.Duration; _jobLog.WriteEntry(this, ("Video duration") + " : " + Duration.ToString(CultureInfo.InvariantCulture), Log.LogEntryType.Information); if (Duration == 0) { _jobLog.WriteEntry(this, ("Video duration 0"), Log.LogEntryType.Error); return(false); } } else { _jobLog.WriteEntry(this, ("Cannot read video duration"), Log.LogEntryType.Error); return(false); } } // Trim the subtitle if (!TrimSubtitle(outputSRTFile, workingPath, startTrim, endTrim, Duration, 0)) { _jobLog.WriteEntry(this, ("Error trimming SRT file"), Log.LogEntryType.Error); return(false); } } // Clean it up and offset the SRT if required if (!SRTValidateAndClean(outputSRTFile, offset)) { _jobLog.WriteEntry(this, ("Cannot clean and set offset for SRT file"), Log.LogEntryType.Error); return(false); } // Check for empty file if (Util.FileIO.FileSize(outputSRTFile) <= 0) { FileIO.TryFileDelete(outputSRTFile); // Delete the empty file _jobLog.WriteEntry(this, ("No valid SRT file found"), Log.LogEntryType.Warning); continue; // check for the next subtitle track } _extractedSRTFile = outputSRTFile; // Save it _jobLog.WriteEntry(this, "Extracted Subtitle file " + outputSRTFile + ", size [KB] " + (FileIO.FileSize(outputSRTFile) / 1024).ToString("N", CultureInfo.InvariantCulture), Log.LogEntryType.Debug); extractedSubtitle = true; // We have success } } return(true); }