Guest User

ffmpeg converter

a guest
Apr 15th, 2018
258
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 43.33 KB | None | 0 0
  1.  
  2. Imports Ffmpeg.Enums
  3. Imports Ffmpeg.Types.EventArgs
  4.  
  5. #Region " Ffmpeg Task "
  6.  
  7. Namespace Ffmpeg.Enums
  8.  
  9.     ''' ----------------------------------------------------------------------------------------------------
  10.     ''' <summary>
  11.     ''' Specifies a <c>FFMPEG.exe</c> task.
  12.     ''' </summary>
  13.     ''' ----------------------------------------------------------------------------------------------------
  14.     Public Enum FfmpegTask As Integer
  15.  
  16.         ''' <summary>
  17.         ''' Converts an audio track to mp3.
  18.         ''' </summary>
  19.         ConvertAudioToMP3 = 0
  20.  
  21.         ''' <summary>
  22.         ''' Checks the metadata of a video container.
  23.         ''' </summary>
  24.         CheckVideoMetadata = 1
  25.  
  26.         ''' <summary>
  27.         ''' Removes the metadata from a video container.
  28.         ''' </summary>
  29.         RemoveVideoMetadata = 2
  30.  
  31.         ''' <summary>
  32.         ''' Re-compresses the audio track of a video container.
  33.         ''' </summary>
  34.         RecompressAudio = 3
  35.  
  36.         ''' <summary>
  37.         ''' Saves the audio track of a video container as Wav format.
  38.         ''' </summary>
  39.         SaveAudioAsWav = 4
  40.  
  41.         ''' <summary>
  42.         ''' Demuxes a video track of a video container.
  43.         ''' </summary>
  44.         DemuxVideo = 5
  45.  
  46.         ''' <summary>
  47.         ''' Demuxes an audio track of a video container.
  48.         ''' </summary>
  49.         DemuxAudio = 6
  50.  
  51.     End Enum
  52.  
  53. End Namespace
  54.  
  55. #End Region
  56.  
  57. #Region " Ffmpeg Audio BitRate "
  58.  
  59. Namespace Ffmpeg.Enums
  60.  
  61.     ''' ----------------------------------------------------------------------------------------------------
  62.     ''' <summary>
  63.     ''' Specifies a <c>FFMPEG.exe</c> audio bitrate.
  64.     ''' </summary>
  65.     ''' ----------------------------------------------------------------------------------------------------
  66.     Public Enum FfmpegAudioBitrate As Integer
  67.  
  68.         Kbps24 = 24
  69.         Kbps32 = 32
  70.         Kbps40 = 40
  71.         Kbps48 = 48
  72.         Kbps56 = 56
  73.         Kbps64 = 64
  74.         Kbps80 = 80
  75.         Kbps96 = 96
  76.         Kbps112 = 112
  77.         Kbps128 = 128
  78.         Kbps144 = 144
  79.         Kbps160 = 160
  80.         Kbps192 = 192
  81.         Kbps224 = 224
  82.         Kbps256 = 256
  83.         Kbps320 = 320
  84.  
  85.     End Enum
  86.  
  87. End Namespace
  88.  
  89. #End Region
  90.  
  91. #Region " Ffmpeg Audio Codec "
  92.  
  93. Namespace Ffmpeg.Enums
  94.  
  95.     ''' ----------------------------------------------------------------------------------------------------
  96.     ''' <summary>
  97.     ''' Specifies a <c>FFMPEG.exe</c> audio codec name.
  98.     ''' </summary>
  99.     ''' ----------------------------------------------------------------------------------------------------
  100.     Public Enum FFMPEGAudioCodec As Integer
  101.  
  102.         ''' <summary>
  103.         ''' LAME MP3.
  104.         ''' </summary>
  105.         libmp3lame
  106.  
  107.         ''' <summary>
  108.         ''' Windows Media Audio.
  109.         ''' </summary>
  110.         wmav2
  111.  
  112.     End Enum
  113.  
  114. End Namespace
  115.  
  116. #End Region
  117.  
  118. #Region " Ffmpeg Started EventArgs "
  119.  
  120. Namespace Ffmpeg.Types.EventArgs
  121.  
  122.     ''' ----------------------------------------------------------------------------------------------------
  123.     ''' <summary>
  124.     ''' Contains the event data of a <see cref="Converter.Started"/> event.
  125.     ''' </summary>
  126.     ''' ----------------------------------------------------------------------------------------------------
  127.     <ImmutableObject(True)>
  128.     Public NotInheritable Class FfmpegStartedEventArgs
  129.  
  130. #Region " Constructors "
  131.  
  132.         ''' ----------------------------------------------------------------------------------------------------
  133.         ''' <summary>
  134.         ''' Prevents a default instance of the <see cref="FfmpegStartedEventArgs"/> class from being created.
  135.         ''' </summary>
  136.         ''' ----------------------------------------------------------------------------------------------------
  137.         Private Sub New()
  138.         End Sub
  139.  
  140.         ''' ----------------------------------------------------------------------------------------------------
  141.         ''' <summary>
  142.         ''' Initializes a new instance of the <see cref="FfmpegStartedEventArgs"/> class.
  143.         ''' </summary>
  144.         ''' ----------------------------------------------------------------------------------------------------
  145.         ''' <param name="file">
  146.         ''' The filepath that was passed as argument to the process.
  147.         ''' </param>
  148.         '''  
  149.         ''' <param name="task">
  150.         ''' The <see cref="FfmpegTask"/> type that is being realized.
  151.         ''' </param>
  152.         ''' ----------------------------------------------------------------------------------------------------
  153.         <DebuggerStepThrough>
  154.         Public Sub New(ByVal file As String,
  155.                        ByVal task As FfmpegTask)
  156.  
  157.             Me.fileb = file
  158.             Me.taskB = task
  159.  
  160.         End Sub
  161.  
  162. #End Region
  163.  
  164. #Region " Properties "
  165.  
  166.         ''' <summary>
  167.         ''' Gets the filepath that was passed as argument to the process.
  168.         ''' </summary>
  169.         Public ReadOnly Property File As String
  170.             Get
  171.                 Return Me.fileb
  172.             End Get
  173.         End Property
  174.         Private ReadOnly fileb As String
  175.  
  176.         ''' <summary>
  177.         ''' Gets the <see cref="FfmpegTask"/> task that is being realized.
  178.         ''' </summary>
  179.         Public ReadOnly Property Task As FfmpegTask
  180.             Get
  181.                 Return Me.taskB
  182.             End Get
  183.         End Property
  184.         Private ReadOnly taskB As FfmpegTask
  185.  
  186. #End Region
  187.  
  188.     End Class
  189.  
  190. End Namespace
  191.  
  192. #End Region
  193.  
  194. #Region " Ffmpeg Exited EventArgs "
  195.  
  196. Namespace Ffmpeg.Types.EventArgs
  197.  
  198.     ''' ----------------------------------------------------------------------------------------------------
  199.     ''' <summary>
  200.     ''' Contains the event data of a <see cref="Converter.Exited"/> event.
  201.     ''' </summary>
  202.     ''' ----------------------------------------------------------------------------------------------------
  203.     <ImmutableObject(True)>
  204.     Public NotInheritable Class FfmpegExitedEventArgs
  205.  
  206. #Region " Constructors "
  207.  
  208.         ''' ----------------------------------------------------------------------------------------------------
  209.         ''' <summary>
  210.         ''' Prevents a default instance of the <see cref="FfmpegExitedEventArgs"/> class from being created.
  211.         ''' </summary>
  212.         ''' ----------------------------------------------------------------------------------------------------
  213.         Private Sub New()
  214.         End Sub
  215.  
  216.         ''' ----------------------------------------------------------------------------------------------------
  217.         ''' <summary>
  218.         ''' Initializes a new instance of the <see cref="FfmpegExitedEventArgs"/> class.
  219.         ''' </summary>
  220.         ''' ----------------------------------------------------------------------------------------------------
  221.         ''' <param name="file">
  222.         ''' The filepath that was passed as argument to the process.
  223.         ''' </param>
  224.         '''
  225.         ''' <param name="task">
  226.         ''' The <see cref="FfmpegTask"/> type that is being realized.
  227.         ''' </param>
  228.         '''
  229.         ''' <param name="errors">
  230.         ''' The error messages of the realized task (if any).
  231.         ''' </param>
  232.         '''
  233.         ''' <param name="exitCode">
  234.         ''' The process exit code.
  235.         ''' </param>
  236.         ''' ----------------------------------------------------------------------------------------------------
  237.         <DebuggerStepThrough>
  238.         Public Sub New(ByVal file As String,
  239.                        ByVal task As FfmpegTask,
  240.                        ByVal errors As List(Of String),
  241.                        ByVal exitCode As Integer)
  242.  
  243.             Me.fileb = file
  244.             Me.taskB = task
  245.             Me.errorsB = errors
  246.             Me.exitCodeB = exitCode
  247.  
  248.         End Sub
  249.  
  250. #End Region
  251.  
  252. #Region " Properties "
  253.  
  254.         ''' <summary>
  255.         ''' Gets the filepath that was passed as argument to the process.
  256.         ''' </summary>
  257.         Public ReadOnly Property File As String
  258.             Get
  259.                 Return Me.fileb
  260.             End Get
  261.         End Property
  262.         Private ReadOnly fileb As String
  263.  
  264.         ''' <summary>
  265.         ''' Gets the <see cref="FfmpegTask"/> task that is being realized.
  266.         ''' </summary>
  267.         Public ReadOnly Property Task As FfmpegTask
  268.             Get
  269.                 Return Me.taskB
  270.             End Get
  271.         End Property
  272.         Private ReadOnly taskB As FfmpegTask
  273.  
  274.         ''' <summary>
  275.         ''' Gets the error messages of the finished task (if any).
  276.         ''' </summary>
  277.         Public ReadOnly Property Errors As List(Of String)
  278.             Get
  279.                 Return Me.errorsB
  280.             End Get
  281.         End Property
  282.         Private ReadOnly errorsB As List(Of String)
  283.  
  284.         ''' <summary>
  285.         ''' Gets the process exit code.
  286.         ''' </summary>
  287.         Public ReadOnly Property ExitCode As Integer
  288.             Get
  289.                 Return Me.exitCodeB
  290.             End Get
  291.         End Property
  292.         Private ReadOnly exitCodeB As Integer
  293.  
  294. #End Region
  295.  
  296.     End Class
  297.  
  298. End Namespace
  299.  
  300. #End Region
  301.  
  302. #Region " Ffmpeg Progress EventArgs "
  303.  
  304. Namespace Ffmpeg.Types.EventArgs
  305.  
  306.     ''' ----------------------------------------------------------------------------------------------------
  307.     ''' <summary>
  308.     ''' Contains the event data of a <see cref="Converter.ProgressChanged"/> event.
  309.     ''' </summary>
  310.     ''' ----------------------------------------------------------------------------------------------------
  311.     <ImmutableObject(True)>
  312.     Public NotInheritable Class FfmpegProgressEventArgs
  313.  
  314. #Region " Constructors "
  315.  
  316.         ''' ----------------------------------------------------------------------------------------------------
  317.         ''' <summary>
  318.         ''' Prevents a default instance of the <see cref="FfmpegProgressEventArgs"/> class from being created.
  319.         ''' </summary>
  320.         ''' ----------------------------------------------------------------------------------------------------
  321.         Private Sub New()
  322.         End Sub
  323.  
  324.         ''' ----------------------------------------------------------------------------------------------------
  325.         ''' <summary>
  326.         ''' Initializes a new instance of the <see cref="FfmpegProgressEventArgs"/> class.
  327.         ''' </summary>
  328.         ''' ----------------------------------------------------------------------------------------------------
  329.         ''' <param name="file">
  330.         ''' The filepath that was passed as argument to the process.
  331.         ''' </param>
  332.         '''
  333.         ''' <param name="task">
  334.         ''' The <see cref="FfmpegTask"/> type that is being realized.
  335.         ''' </param>
  336.         '''
  337.         ''' <param name="percent">
  338.         ''' The <c>FFMPEG.exe</c> task percent done.
  339.         ''' </param>
  340.         '''
  341.         ''' <param name="writtenBytes">
  342.         ''' The total amount of written bytes.
  343.         ''' </param>
  344.         '''
  345.         ''' <param name="videoDuration">
  346.         ''' The input video duration.
  347.         ''' </param>
  348.         '''
  349.         ''' <param name="time">
  350.         ''' The processed video time.
  351.         ''' </param>
  352.         ''' ----------------------------------------------------------------------------------------------------
  353.         <DebuggerStepThrough>
  354.         Public Sub New(ByVal file As String,
  355.                        ByVal task As FfmpegTask,
  356.                        ByVal percent As Integer,
  357.                        ByVal writtenBytes As Double,
  358.                        ByVal videoDuration As TimeSpan,
  359.                        ByVal time As TimeSpan)
  360.  
  361.             Me.fileb = file
  362.             Me.taskB = task
  363.             Me.videoDurationB = videoDuration
  364.             Me.timeB = time
  365.             Me.writtenBytesB = writtenBytes
  366.             Me.percentB = percent
  367.  
  368.         End Sub
  369.  
  370. #End Region
  371.  
  372. #Region " Properties "
  373.  
  374.         ''' <summary>
  375.         ''' Gets the filepath that was passed as argument to the process.
  376.         ''' </summary>
  377.         Public ReadOnly Property File As String
  378.             Get
  379.                 Return Me.fileb
  380.             End Get
  381.         End Property
  382.         Private ReadOnly fileb As String
  383.  
  384.         ''' <summary>
  385.         ''' The input Video Duration.
  386.         ''' </summary>
  387.         Public ReadOnly Property VideoDuration As TimeSpan
  388.             Get
  389.                 Return Me.videoDurationB
  390.             End Get
  391.         End Property
  392.         Private ReadOnly videoDurationB As TimeSpan
  393.  
  394.         ''' <summary>
  395.         ''' The processed video time.
  396.         ''' </summary>
  397.         Public ReadOnly Property Time As TimeSpan
  398.             Get
  399.                 Return Me.timeB
  400.             End Get
  401.         End Property
  402.         Private ReadOnly timeB As TimeSpan
  403.  
  404.         ''' <summary>
  405.         ''' The total amount of written bytes.
  406.         ''' </summary>
  407.         Public ReadOnly Property WrittenBytes As Double
  408.             Get
  409.                 Return Me.writtenBytesB
  410.             End Get
  411.         End Property
  412.         Private ReadOnly writtenBytesB As Double
  413.  
  414.         ''' <summary>
  415.         ''' Gets the <see cref="FfmpegTask"/> task that is being realized.
  416.         ''' </summary>
  417.         Public ReadOnly Property Task As FfmpegTask
  418.             Get
  419.                 Return Me.taskB
  420.             End Get
  421.         End Property
  422.         Private ReadOnly taskB As FfmpegTask
  423.  
  424.         ''' <summary>
  425.         ''' Gets the <c>FFMPEG.exe</c> task percent done.
  426.         ''' </summary>
  427.         Public ReadOnly Property Percent As Integer
  428.             Get
  429.                 Return Me.percentB
  430.             End Get
  431.         End Property
  432.         Private ReadOnly percentB As Integer
  433.  
  434. #End Region
  435.  
  436.     End Class
  437.  
  438. End Namespace
  439.  
  440. #End Region
  441.  
  442. #Region " Ffmpeg Converter "
  443.  
  444. #Region " Public Members Summary "
  445.  
  446. #Region " Constructors "
  447.  
  448. ' New(String)
  449.  
  450. #End Region
  451.  
  452. #Region " Events "
  453.  
  454. ' Started As EventHandler(Of FfmpegStartedEventArgs)
  455. ' Exited As EventHandler(Of FfmpegExitedEventArgs)
  456. ' ProgressChanged As EventHandler(Of FfmpegProgressEventArgs)
  457.  
  458. #End Region
  459.  
  460. #Region " Properties "
  461.  
  462. ' FilePath As String
  463. ' Process As Process
  464. ' Exists As Boolean
  465.  
  466. #End Region
  467.  
  468. #Region " Functions "
  469.  
  470. ' VideoContainsMetadata(String) As Boolean
  471. ' RemoveVideoMetadata(String, String, Boolean, Opt: Integer) As Integer
  472. ' RecompressAudio(String, String, Boolean, FfmpegAudioCodec, FfmpegAudioBitrate, Opt: Boolean, Opt: Integer) As Integer
  473. ' SaveAudioAsWav(String, String, Boolean, Opt: Integer) As Integer
  474. ' DemuxAudio(String, String, Boolean, Opt: Integer) As Integer
  475. ' DemuxVideo(String, String, Boolean, Opt: Integer) As Integer
  476.  
  477. #End Region
  478.  
  479. #End Region
  480.  
  481. #Region " CommandLine Parameter legend "
  482.  
  483. '-y        | Overwrite output files without asking.
  484. '-n        | Do not overwrite output files, and exit immediately if a specified output file already exists.
  485. '-threads  |  Specify the cpu threads to use.
  486. '-nostdin  | Disable interaction on standard input.
  487. '-vcodec   | Set the video codec.
  488. '-acodec   | Set the audio codec.
  489. '-vn       | Disable video recording.
  490. '-an       | Disable audio recording.
  491.  
  492. ' -c copy -map_metadata -1
  493. ' Don't add metadata.
  494.  
  495. #End Region
  496.  
  497. #Region " Usage Examples "
  498.  
  499. 'Private WithEvents ff As New Converter(".\FFMPEG.exe")
  500. '
  501. 'Private Shadows Sub Shown() Handles MyBase.Shown
  502. '
  503. '    ' Checks if FFMPEG executable is available.
  504. '    MsgBox(ff.Exists)
  505. '
  506. '    ' Checks if a video has metadata
  507. '    MsgBox(ff.VideoContainsMetadata("C:\Video.mkv"))
  508. '
  509. '    ' Remove metadata from video
  510. '    ff.RemoveVideoMetadata("C:\Input.mkv", "C:\Output.mkv", True, 4)
  511. '
  512. '    ' reCompress the audio track of a video
  513. '    ff.RecompressAudio("C:\Input.mkv", "C:\Output.mkv", True, FfmpegAudioCodec.libmp3lame, FfmpegAudioBitrate.Kbps128, True, 4)
  514. '
  515. '    ' Demuxes the audio track of file
  516. '    ff.DemuxAudio("C:\Input.wmv", "C:\Output.wma", True, 4)
  517. '
  518. '    ' Demuxes the video track of file
  519. '    ff.DemuxVideo("C:\Input.mp4", "C:\Output.h264", True, 4)
  520. '
  521. '    ' Demuxes the video track of file
  522. '    ff.SaveAudioAsWav("C:\Input.mkv", "C:\Output.wav", True, 4)
  523. '
  524. 'End Sub
  525. '
  526. 'Private Sub Ffmeg_Started(ByVal sender As Object, ByVal e As FfmpegStartedEventArgs) _
  527. 'Handles ff.Started
  528. '
  529. '    ProgressBar1.Value = ProgressBar1.Minimum
  530. '
  531. '    Dim sb As New System.Text.StringBuilder
  532. '
  533. '    sb.AppendLine(String.Format("Started an ""{0}"" operation", e.Task.ToString()))
  534. '    sb.AppendLine(String.Format("Input file is: ""{0}""", e.File))
  535. '    sb.AppendLine(String.Format("FFMPEG process PID is: ""{0}""", DirectCast(sender, Converter).Process.Id))
  536. '
  537. '    MessageBox.Show(sb.ToString(), "FFMPEG", MessageBoxButtons.OK, MessageBoxIcon.Information)
  538. '
  539. 'End Sub
  540. '
  541. 'Private Sub Ffmeg_Exited(ByVal sender As Object, ByVal e As FfmpegExitedEventArgs) _
  542. 'Handles ff.Exited
  543. '
  544. '    Dim sb As New System.Text.StringBuilder
  545. '
  546. '    sb.AppendLine(String.Format("Finished an ""{0}"" operation", e.Task.ToString()))
  547. '    sb.AppendLine(String.Format("Input file is: ""{0}""", e.File))
  548. '    sb.AppendLine(String.Format("FFMPEG process PID is: {0}", DirectCast(sender, Process).Id))
  549. '
  550. '    If e.Errors.Count <> 0 Then
  551. '        sb.AppendLine(String.Format("Errors during operation: {0}", String.Join(Environment.NewLine, e.Errors)))
  552. '    End If
  553. '
  554. '    MessageBox.Show(sb.ToString(), "FFMPEG", MessageBoxButtons.OK, MessageBoxIcon.Information)
  555. '
  556. 'End Sub
  557. '
  558. 'Private Sub Ffmeg_ProgressChanged(ByVal sender As Object, e As FfmpegProgressEventArgs) _
  559. 'Handles ff.ProgressChanged
  560. '
  561. '    ProgressBar1.Value = e.Percent
  562. '
  563. '    Label1.Text = "Percent Done: " & CStr(e.Percent) & "%"
  564. '    Label2.Text = "Video Duration: " & e.VideoDuration.ToString("hh\:mm\:ss")
  565. '    Label3.Text = "Written Duration: " & e.Time.ToString("hh\:mm\:ss")
  566. '    Label4.Text = "Written Data: " & (e.WrittenBytes / 1024L * 1024L).ToString("n1") & "MB"
  567. '
  568. 'End Sub
  569.  
  570. #End Region
  571.  
  572. Namespace Ffmpeg.Types
  573.  
  574.     ''' ----------------------------------------------------------------------------------------------------
  575.     ''' <summary>
  576.     ''' A wrapper of <c>FFMPEG.exe</c> application.
  577.     ''' </summary>
  578.     ''' ----------------------------------------------------------------------------------------------------
  579.     ''' <example> This is a code example.
  580.     ''' <code>
  581.     ''' Private WithEvents ff As New Converter(".\FFMPEG.exe")
  582.     '''
  583.     ''' Private Shadows Sub Shown() Handles MyBase.Shown
  584.     '''
  585.     '''     ' Checks if FFMPEG executable is available.
  586.     '''     MsgBox(ff.Exists)
  587.     '''
  588.     '''     ' Checks if a video has metadata
  589.     '''     MsgBox(ff.VideoContainsMetadata("C:\Video.mkv"))
  590.     '''
  591.     '''     ' Remove metadata from video
  592.     '''     ff.RemoveVideoMetadata("C:\Input.mkv", "C:\Output.mkv", True, 4)
  593.     '''
  594.     '''     ' reCompress the audio track of a video
  595.     '''     ff.RecompressAudio("C:\Input.mkv", "C:\Output.mkv", True, FfmpegAudioCodec.libmp3lame, FfmpegAudioBitrate.Kbps128, True, 4)
  596.     '''
  597.     '''     ' Demuxes the audio track of file
  598.     '''     ff.DemuxAudio("C:\Input.wmv", "C:\Output.wma", True, 4)
  599.     '''
  600.     '''     ' Demuxes the video track of file
  601.     '''     ff.DemuxVideo("C:\Input.mp4", "C:\Output.h264", True, 4)
  602.     '''
  603.     '''     ' Demuxes the video track of file
  604.     '''     ff.SaveAudioAsWav("C:\Input.mkv", "C:\Output.wav", True, 4)
  605.     '''
  606.     ''' End Sub
  607.     '''
  608.     ''' Private Sub Ffmeg_Started(ByVal sender As Object, ByVal e As FfmpegStartedEventArgs) _
  609.     ''' Handles ff.Started
  610.     '''
  611.     '''     ProgressBar1.Value = ProgressBar1.Minimum
  612.     '''
  613.     '''     Dim sb As New System.Text.StringBuilder
  614.     '''
  615.     '''     sb.AppendLine(String.Format("Started an ""{0}"" operation", e.Task.ToString()))
  616.     '''     sb.AppendLine(String.Format("Input file is: ""{0}""", e.File))
  617.     '''     sb.AppendLine(String.Format("FFMPEG process PID is: ""{0}""", DirectCast(sender, Converter).Process.Id))
  618.     '''
  619.     '''     MessageBox.Show(sb.ToString(), "FFMPEG", MessageBoxButtons.OK, MessageBoxIcon.Information)
  620.     '''
  621.     ''' End Sub
  622.     '''
  623.     ''' Private Sub Ffmeg_Exited(ByVal sender As Object, ByVal e As FfmpegExitedEventArgs) _
  624.     ''' Handles ff.Exited
  625.     '''
  626.     '''     Dim sb As New System.Text.StringBuilder
  627.     '''
  628.     '''     sb.AppendLine(String.Format("Finished an ""{0}"" operation", e.Task.ToString()))
  629.     '''     sb.AppendLine(String.Format("Input file is: ""{0}""", e.File))
  630.     '''     sb.AppendLine(String.Format("FFMPEG process PID is: {0}", DirectCast(sender, Process).Id))
  631.     '''
  632.     '''     If e.Errors.Count &lt;&gt; 0 Then
  633.     '''         sb.AppendLine(String.Format("Errors during operation: {0}", String.Join(Environment.NewLine, e.Errors)))
  634.     '''     End If
  635.     '''
  636.     '''     MessageBox.Show(sb.ToString(), "FFMPEG", MessageBoxButtons.OK, MessageBoxIcon.Information)
  637.     '''
  638.     ''' End Sub
  639.     '''
  640.     ''' Private Sub Ffmeg_ProgressChanged(ByVal sender As Object, e As FfmpegProgressEventArgs) _
  641.     ''' Handles ff.ProgressChanged
  642.     '''
  643.     '''     ProgressBar1.Value = e.Percent
  644.     '''
  645.     '''     Label1.Text = "Percent Done: " &amp; CStr(e.Percent) &amp; "%"
  646.     '''     Label2.Text = "Video Duration: " &amp; e.VideoDuration.ToString("hh\:mm\:ss")
  647.     '''     Label3.Text = "Written Duration: " &amp; e.Time.ToString("hh\:mm\:ss")
  648.     '''     Label4.Text = "Written Data: " &amp; (e.WrittenBytes / 1024L * 1024L).ToString("n1") &amp; "MB"
  649.     '''
  650.     ''' End Sub
  651.     ''' </code>
  652.     ''' </example>
  653.     ''' ----------------------------------------------------------------------------------------------------
  654.     <ImmutableObject(True)>
  655.     Public NotInheritable Class Converter : Implements IDisposable
  656.  
  657. #Region " Private Fields "
  658.  
  659.         ''' <summary>
  660.         ''' The <c>FFMPEG.exe</c> <see cref="Process"/> instance
  661.         ''' </summary>
  662.         Private ReadOnly processB As Process
  663.  
  664. #End Region
  665.  
  666. #Region " Events "
  667.  
  668.         ''' <summary>
  669.         ''' Event raised when the <c>FFMPEG.exe</c> process has been started.
  670.         ''' </summary>
  671.         Public Event Started As EventHandler(Of FfmpegStartedEventArgs)
  672.  
  673.         ''' <summary>
  674.         ''' Event raised when the <c>FFMPEG.exe</c> process has exited.
  675.         ''' </summary>
  676.         Public Event Exited As EventHandler(Of FfmpegExitedEventArgs)
  677.  
  678.         ''' <summary>
  679.         ''' Event raised when <c>FFMPEG.exe</c> task progress has been changed.
  680.         ''' </summary>
  681.         Public Event ProgressChanged As EventHandler(Of FfmpegProgressEventArgs)
  682.  
  683. #End Region
  684.  
  685. #Region " Properties "
  686.  
  687.         ''' ----------------------------------------------------------------------------------------------------
  688.         ''' <summary>
  689.         ''' Gets the <c>FFMPEG.exe</c> filepath.
  690.         ''' </summary>
  691.         ''' ----------------------------------------------------------------------------------------------------
  692.         Public ReadOnly Property FilePath As String
  693.             Get
  694.                 Return Me.filepathB
  695.             End Get
  696.         End Property
  697.         ''' ----------------------------------------------------------------------------------------------------
  698.         ''' <summary>
  699.         ''' ( Backing field )
  700.         ''' The <c>FFMPEG.exe</c> filepath.
  701.         ''' </summary>
  702.         ''' ----------------------------------------------------------------------------------------------------
  703.         Private filepathB As String
  704.  
  705.         ''' ----------------------------------------------------------------------------------------------------
  706.         ''' <summary>
  707.         ''' Gets a value indicating whether the <c>FFMPEG.exe</c> file Exists.
  708.         ''' </summary>
  709.         ''' ----------------------------------------------------------------------------------------------------
  710.         Public ReadOnly Property Exists As Boolean
  711.             Get
  712.                 Return File.Exists(Me.FilePath)
  713.             End Get
  714.         End Property
  715.  
  716.         ''' ----------------------------------------------------------------------------------------------------
  717.         ''' <summary>
  718.         ''' Gets the <c>FFMPEG.exe</c> <see cref="Process"/> instance.
  719.         ''' </summary>
  720.         ''' ----------------------------------------------------------------------------------------------------
  721.         Public ReadOnly Property Process As Process
  722.             Get
  723.                 Return Me.processB
  724.             End Get
  725.         End Property
  726.  
  727. #End Region
  728.  
  729. #Region " Constructors "
  730.  
  731.         ''' ----------------------------------------------------------------------------------------------------
  732.         ''' <summary>
  733.         ''' Prevents a default instance of the <see cref="Converter"/> class from being created.
  734.         ''' </summary>
  735.         ''' ----------------------------------------------------------------------------------------------------
  736.         Private Sub New()
  737.         End Sub
  738.  
  739.         ''' ----------------------------------------------------------------------------------------------------
  740.         ''' <summary>
  741.         ''' Initializes a new instance of the <see cref="Converter" /> class.
  742.         ''' </summary>
  743.         ''' ----------------------------------------------------------------------------------------------------
  744.         ''' <param name="filepath">
  745.         ''' The <c>FFMPEG.exe</c> filepath.
  746.         ''' </param>
  747.         ''' ----------------------------------------------------------------------------------------------------
  748.         <DebuggerStepThrough>
  749.         Public Sub New(ByVal filepath As String)
  750.  
  751.             Me.filepathB = filepath
  752.  
  753.             Me.processB =
  754.                 New Process With {.StartInfo =
  755.                     New ProcessStartInfo With {
  756.                         .FileName = filepath,
  757.                         .CreateNoWindow = True,
  758.                         .UseShellExecute = False,
  759.                         .RedirectStandardError = True,
  760.                         .RedirectStandardOutput = True,
  761.                         .StandardErrorEncoding = Encoding.Default,
  762.                         .StandardOutputEncoding = Encoding.Default
  763.                     }
  764.                 }
  765.  
  766.         End Sub
  767.  
  768. #End Region
  769.  
  770. #Region " Public Methods "
  771.  
  772.         ''' ----------------------------------------------------------------------------------------------------
  773.         ''' <summary>
  774.         ''' Determines whether a video file contains metadata fields.
  775.         ''' </summary>
  776.         ''' ----------------------------------------------------------------------------------------------------
  777.         ''' <param name="videoFilepath">
  778.         ''' The source video filepath.
  779.         ''' </param>
  780.         ''' ----------------------------------------------------------------------------------------------------
  781.         ''' <returns>
  782.         ''' <see langword="True"/> if video file contains metadata fields, otherwise, <see langword="False"/>.
  783.         ''' </returns>
  784.         ''' ----------------------------------------------------------------------------------------------------
  785.         Public Function VideoContainsMetadata(ByVal videoFilepath As String) As Boolean
  786.  
  787.             ' Unique temp file to write the FFMPEG.exe output.
  788.             Dim tempFile As String = Path.GetTempFileName()
  789.  
  790.             Me.processB.StartInfo.Arguments =
  791.               String.Format("-y -i ""{0}"" -f ffmetadata ""{1}""",
  792.                             videoFilepath, tempFile)
  793.  
  794.             Dim exitCode As Integer = Me.Run(Me.processB, videoFilepath, FfmpegTask.CheckVideoMetadata)
  795.  
  796.             Return File.ReadAllText(tempFile).Replace(";FFMETADATA1", "").Trim.Length <> 0
  797.  
  798.         End Function
  799.  
  800.         ''' ----------------------------------------------------------------------------------------------------
  801.         ''' <summary>
  802.         ''' Removes the metadata tags from a video file.
  803.         ''' </summary>
  804.         ''' ----------------------------------------------------------------------------------------------------
  805.         ''' <param name="inputFilepath">
  806.         ''' The source video filepath.
  807.         ''' </param>
  808.         '''
  809.         ''' <param name="outputFilepath">
  810.         ''' The target video filepath.
  811.         ''' </param>
  812.         '''
  813.         ''' <param name="overWrite">
  814.         ''' A value indicating whether to overwrite the target filepath if already exists.
  815.         ''' </param>
  816.         '''
  817.         ''' <param name="threads">
  818.         ''' The amount of threads to use.
  819.         ''' <para></para>
  820.         ''' Default value is <c>1</c>.
  821.         ''' </param>
  822.         ''' ----------------------------------------------------------------------------------------------------
  823.         ''' <returns>
  824.         ''' The process exit code.
  825.         ''' </returns>
  826.         ''' ----------------------------------------------------------------------------------------------------
  827.         Public Function RemoveVideoMetadata(ByVal inputFilepath As String,
  828.                                             ByVal outputFilepath As String,
  829.                                             ByVal overWrite As Boolean,
  830.                                             Optional ByVal threads As Integer = 1) As Integer
  831.  
  832.             Me.processB.StartInfo.Arguments =
  833.               String.Format("-nostdin -threads {0} {1} -i ""{2}"" -c copy -map_metadata -1 ""{3}""",
  834.                             threads,
  835.                             If(overWrite, "-y", "-n"),
  836.                             inputFilepath,
  837.                             outputFilepath)
  838.  
  839.             Return Me.Run(Me.processB, inputFilepath, FfmpegTask.RemoveVideoMetadata)
  840.  
  841.         End Function
  842.  
  843.         ''' ----------------------------------------------------------------------------------------------------
  844.         ''' <summary>
  845.         ''' ReCompress the audio track of a video file.
  846.         ''' </summary>
  847.         ''' ----------------------------------------------------------------------------------------------------
  848.         ''' <param name="inputFilepath">
  849.         ''' The source video filepath.
  850.         ''' </param>
  851.         '''
  852.         ''' <param name="outputFilepath">
  853.         ''' The target video filepath.
  854.         ''' </param>
  855.         '''
  856.         ''' <param name="overWrite">
  857.         ''' A value indicating whether to overwrite the target filepath if already exists.
  858.         ''' </param>
  859.         '''
  860.         ''' <param name="audioCodec">
  861.         ''' The audio codec to use.
  862.         ''' </param>
  863.         '''
  864.         ''' <param name="bitrate">
  865.         ''' The audio bitrate.
  866.         ''' </param>
  867.         '''
  868.         ''' <param name="preserveMetadata">
  869.         ''' A value indicating whether to preserve the source video metadata in the target video.
  870.         ''' </param>
  871.         '''
  872.         ''' <param name="threads">
  873.         ''' The amount of threads to use.
  874.         ''' <para></para>
  875.         ''' Default value is <c>1</c>.
  876.         ''' </param>
  877.         ''' ----------------------------------------------------------------------------------------------------
  878.         ''' <returns>
  879.         ''' The process exit code.
  880.         ''' </returns>
  881.         ''' ----------------------------------------------------------------------------------------------------
  882.         Public Function RecompressAudio(ByVal inputFilepath As String,
  883.                                         ByVal outputFilepath As String,
  884.                                         ByVal overWrite As Boolean,
  885.                                         ByVal audioCodec As FFMPEGAudioCodec,
  886.                                         ByVal bitrate As FfmpegAudioBitrate,
  887.                                         Optional ByVal preserveMetadata As Boolean = False,
  888.                                         Optional ByVal threads As Integer = 1) As Integer
  889.  
  890.             Me.processB.StartInfo.Arguments =
  891.               String.Format("-nostdin -threads {0} {1} -i ""{2}"" {3} -vcodec copy -acodec {4} -ab {5} ""{6}""",
  892.                             threads,
  893.                             If(overWrite, "-y", "-n"),
  894.                             inputFilepath,
  895.                             If(preserveMetadata, "", "-c copy -map_metadata -1"),
  896.                             audioCodec.ToString(),
  897.                             CStr(bitrate) & "k",
  898.                             outputFilepath)
  899.  
  900.             Return Me.Run(Me.processB, inputFilepath, FfmpegTask.RecompressAudio)
  901.  
  902.         End Function
  903.  
  904.         ''' ----------------------------------------------------------------------------------------------------
  905.         ''' <summary>
  906.         ''' Demuxes the audio track of a video file to save it as WAV format.
  907.         ''' </summary>
  908.         ''' ----------------------------------------------------------------------------------------------------
  909.         ''' <param name="inputFilepath">
  910.         ''' The source video filepath.
  911.         ''' </param>
  912.         '''
  913.         ''' <param name="outputFilepath">
  914.         ''' The target audio filepath.
  915.         ''' </param>
  916.         '''
  917.         ''' <param name="overWrite">
  918.         ''' A value indicating whether to overwrite the target filepath if already exists.
  919.         ''' </param>
  920.         '''
  921.         ''' <param name="threads">
  922.         ''' The amount of threads to use.
  923.         ''' <para></para>
  924.         ''' Default value is <c>1</c>.
  925.         ''' </param>
  926.         ''' ----------------------------------------------------------------------------------------------------
  927.         ''' <returns>
  928.         ''' The process exit code.
  929.         ''' </returns>
  930.         ''' ----------------------------------------------------------------------------------------------------
  931.         Public Function SaveAudioAsWav(ByVal inputFilepath As String,
  932.                                        ByVal outputFilepath As String,
  933.                                        ByVal overWrite As Boolean,
  934.                                        Optional ByVal threads As Integer = 1) As Integer
  935.  
  936.             Me.processB.StartInfo.Arguments =
  937.               String.Format("-nostdin -threads {0} {1} -i ""{2}"" -acodec pcm_s16le -ac 1 -vn ""{3}""",
  938.                             threads,
  939.                             If(overWrite, "-y", "-n"),
  940.                             inputFilepath,
  941.                             outputFilepath)
  942.  
  943.             Return Me.Run(Me.processB, inputFilepath, FfmpegTask.SaveAudioAsWav)
  944.  
  945.         End Function
  946.  
  947.         ''' ----------------------------------------------------------------------------------------------------
  948.         ''' <summary>
  949.         ''' Demuxes the video track of a video file.
  950.         ''' </summary>
  951.         ''' ----------------------------------------------------------------------------------------------------
  952.         ''' <param name="inputFilepath">
  953.         ''' The source video filepath.
  954.         ''' </param>
  955.         '''
  956.         ''' <param name="outputFilepath">
  957.         ''' The target video filepath.
  958.         ''' </param>
  959.         '''
  960.         ''' <param name="overWrite">
  961.         ''' A value indicating whether to overwrite the target filepath if already exists.
  962.         ''' </param>
  963.         '''
  964.         ''' <param name="threads">
  965.         ''' The amount of threads to use.
  966.         ''' <para></para>
  967.         ''' Default value is <c>1</c>.
  968.         ''' </param>
  969.         ''' ----------------------------------------------------------------------------------------------------
  970.         ''' <returns>
  971.         ''' The process exit code.
  972.         ''' </returns>
  973.         ''' ----------------------------------------------------------------------------------------------------
  974.         Public Function DemuxVideo(ByVal inputFilepath As String,
  975.                                    ByVal outputFilepath As String,
  976.                                    ByVal overWrite As Boolean,
  977.                                    Optional ByVal threads As Integer = 1) As Integer
  978.  
  979.             Me.processB.StartInfo.Arguments =
  980.               String.Format("-nostdin -threads {0} {1} -i ""{2}"" -vcodec copy -an ""{3}""",
  981.                             threads,
  982.                             If(overWrite, "-y", "-n"),
  983.                             inputFilepath,
  984.                             outputFilepath)
  985.  
  986.             Return Me.Run(Me.processB, inputFilepath, FfmpegTask.DemuxVideo)
  987.  
  988.         End Function
  989.  
  990.         ''' ----------------------------------------------------------------------------------------------------
  991.         ''' <summary>
  992.         ''' Demuxes the audio track of a video file.
  993.         ''' </summary>
  994.         ''' ----------------------------------------------------------------------------------------------------
  995.         ''' <param name="inputFilepath">
  996.         ''' The source video filepath.
  997.         ''' </param>
  998.         '''
  999.         ''' <param name="outputFilepath">
  1000.         ''' The target audio filepath.
  1001.         ''' </param>
  1002.         '''
  1003.         ''' <param name="overWrite">
  1004.         ''' A value indicating whether to overwrite the target filepath if already exists.
  1005.         ''' </param>
  1006.         '''
  1007.         ''' <param name="threads">
  1008.         ''' The amount of threads to use.
  1009.         ''' <para></para>
  1010.         ''' Default value is <c>1</c>.
  1011.         ''' </param>
  1012.         ''' ----------------------------------------------------------------------------------------------------
  1013.         ''' <returns>
  1014.         ''' The process exit code.
  1015.         ''' </returns>
  1016.         ''' ----------------------------------------------------------------------------------------------------
  1017.         Public Function DemuxAudio(ByVal inputFilepath As String,
  1018.                                    ByVal outputFilepath As String,
  1019.                                    ByVal overWrite As Boolean,
  1020.                                    Optional ByVal threads As Integer = 1) As Integer
  1021.  
  1022.             Me.processB.StartInfo.Arguments =
  1023.               String.Format("-nostdin -threads {0} {1} -i ""{2}"" -acodec copy -vn ""{3}""",
  1024.                             threads,
  1025.                             If(overWrite, "-y", "-n"),
  1026.                             inputFilepath,
  1027.                             outputFilepath)
  1028.  
  1029.             Return Me.Run(Me.processB, inputFilepath, FfmpegTask.DemuxAudio)
  1030.  
  1031.         End Function
  1032.  
  1033. #End Region
  1034.  
  1035. #Region " Private Methods "
  1036.  
  1037.         ''' ----------------------------------------------------------------------------------------------------
  1038.         ''' <summary>
  1039.         ''' Runs a specific task of <c>FFMPEG.exe</c>.
  1040.         ''' </summary>
  1041.         ''' ----------------------------------------------------------------------------------------------------
  1042.         <DebuggerStepThrough>
  1043.         Private Function Run(ByVal p As Process,
  1044.                              ByVal file As String,
  1045.                              ByVal task As FfmpegTask) As Integer
  1046.  
  1047.             Dim outputLine As String
  1048.             Dim videoDuration As TimeSpan
  1049.             Dim time As TimeSpan
  1050.             Dim errors As New List(Of String)
  1051.             Dim exitCode As Integer
  1052.  
  1053.             p.Start()
  1054.  
  1055.             If Me.StartedEvent IsNot Nothing Then
  1056.                 Dim startedArgs As New FfmpegStartedEventArgs(file, task)
  1057.                 RaiseEvent Started(Me, startedArgs)
  1058.             End If
  1059.  
  1060.             If Me.ProgressChangedEvent IsNot Nothing Then
  1061.  
  1062.                 While Not p.StandardError.EndOfStream
  1063.  
  1064.                     ' Parse the Input Video Duration to calculate the percentage.
  1065.                     Do Until (videoDuration.TotalMilliseconds > 0)
  1066.  
  1067.                         outputLine = p.StandardError.ReadLine().ToLower()
  1068.  
  1069.                         If outputLine.Contains("duration") Then
  1070.  
  1071.                             Try
  1072.                                 videoDuration = TimeSpan.Parse(outputLine.Replace("duration:", "").
  1073.                                                                           Split(","c).FirstOrDefault)
  1074.  
  1075.                             Catch ex As FormatException
  1076.                                 videoDuration = TimeSpan.Parse("24:00:00") ' 00:00:00
  1077.  
  1078.                             End Try
  1079.  
  1080.                         End If
  1081.  
  1082.                     Loop
  1083.  
  1084.                     ' Parse the percentage and other values.
  1085.                     outputLine = p.StandardError.ReadLine().ToLower()
  1086.  
  1087.                     If outputLine.StartsWith("frame=") Then
  1088.                         time = TimeSpan.Parse(outputLine.Split("="c)(5).Split.First())
  1089.  
  1090.                         Dim progressArgs As New FfmpegProgressEventArgs(
  1091.                             file,
  1092.                             task,
  1093.                             CInt((time.TotalSeconds / videoDuration.TotalSeconds) * 100),
  1094.                             CDbl(outputLine.Split("="c)(4).Trim.Split.First.Replace("kb", "")) / 1024,
  1095.                             videoDuration,
  1096.                             time)
  1097.  
  1098.                         RaiseEvent ProgressChanged(Me, progressArgs)
  1099.  
  1100.                     ElseIf (outputLine.Contains("error") OrElse outputLine.Contains("warning")) Then
  1101.                         errors.Add(outputLine)
  1102. #If DEBUG Then
  1103.                         Debug.WriteLine("[DEBUG] FFMPEG Error: " & outputLine)
  1104. #End If
  1105.  
  1106.                     End If
  1107.  
  1108.                 End While
  1109.  
  1110.             Else
  1111.                 p.WaitForExit()
  1112.  
  1113.             End If
  1114.  
  1115.             exitCode = p.ExitCode
  1116.  
  1117.             If Me.ExitedEvent IsNot Nothing Then
  1118.                 Dim exitedArgs As New FfmpegExitedEventArgs(file, task, errors, exitCode)
  1119.                 RaiseEvent Exited(Me, exitedArgs)
  1120.             End If
  1121.  
  1122.             ' FFMPEG.Close()
  1123.             Return exitCode
  1124.  
  1125.         End Function
  1126.  
  1127. #End Region
  1128.  
  1129. #Region " IDisposable Implementation "
  1130.  
  1131.         ''' ----------------------------------------------------------------------------------------------------
  1132.         ''' <summary>
  1133.         ''' Flag to detect redundant calls when disposing.
  1134.         ''' </summary>
  1135.         ''' ----------------------------------------------------------------------------------------------------
  1136.         Private isDisposed As Boolean = False
  1137.  
  1138.         ''' ----------------------------------------------------------------------------------------------------
  1139.         ''' <summary>
  1140.         ''' Releases all the resources used by this instance.
  1141.         ''' </summary>
  1142.         ''' ----------------------------------------------------------------------------------------------------
  1143.         <DebuggerStepThrough>
  1144.         Public Sub Dispose() Implements IDisposable.Dispose
  1145.             Me.Dispose(isDisposing:=True)
  1146.             GC.SuppressFinalize(obj:=Me)
  1147.         End Sub
  1148.  
  1149.         ''' ----------------------------------------------------------------------------------------------------
  1150.         ''' <summary>
  1151.         ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  1152.         ''' </summary>
  1153.         ''' ----------------------------------------------------------------------------------------------------
  1154.         ''' <param name="isDisposing">
  1155.         ''' <see langword="True"/>  to release both managed and unmanaged resources;
  1156.         ''' <see langword="False"/> to release only unmanaged resources.
  1157.         ''' </param>
  1158.         ''' ----------------------------------------------------------------------------------------------------
  1159.         <DebuggerStepThrough>
  1160.         Private Sub Dispose(ByVal isDisposing As Boolean)
  1161.  
  1162.             If (Not Me.isDisposed) AndAlso (isDisposing) Then
  1163.  
  1164.                 If (Me.processB IsNot Nothing) Then
  1165.  
  1166.                     'Try
  1167.                     '    Me.processB.Kill()
  1168.                     '
  1169.                     'Catch ex As Exception
  1170.                     '
  1171.                     'End Try
  1172.  
  1173.                     Me.processB.Dispose()
  1174.                     Me.filepathB = ""
  1175.                 End If
  1176.  
  1177.             End If
  1178.  
  1179.             Me.isDisposed = True
  1180.  
  1181.         End Sub
  1182.  
  1183. #End Region
  1184.  
  1185.     End Class
  1186.  
  1187. End Namespace
  1188.  
  1189. #End Region
Advertisement
Add Comment
Please, Sign In to add comment