public void Can_TranscodeUsingConversionOptions()
        {
            string outputPath = string.Format("{0}/Transcode_Test.avi", Path.GetDirectoryName(_outputFilePath));

            var inputFile = new MediaFile { Filename = _inputFilePath };
            var outputFile = new MediaFile { Filename = outputPath };
            var conversionOptions = new ConversionOptions
            {
                MaxVideoDuration = TimeSpan.FromSeconds(30),
                VideoAspectRatio = VideoAspectRatio.R16_9,
                VideoSize = VideoSize.Hd720,
                AudioSampleRate = AudioSampleRate.Hz44100
            };


            using (var engine = new Engine())
                engine.Convert(inputFile, outputFile, conversionOptions);
        }
        public void Can_CutVideo()
        {
            string filePath = @"{0}\Cut_Video_Test.mp4";
            string outputPath = string.Format(filePath, Path.GetDirectoryName(_outputFilePath));

            var inputFile = new MediaFile { Filename = _inputFilePath };
            var outputFile = new MediaFile { Filename = outputPath };

            using (var engine = new Engine())
            {
                engine.ConvertProgressEvent += engine_ConvertProgressEvent;
                engine.ConversionCompleteEvent += engine_ConversionCompleteEvent;

                engine.GetMetadata(inputFile);

                ConversionOptions options = new ConversionOptions();
                options.CutMedia(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(25));

                engine.Convert(inputFile, outputFile, options);
                engine.GetMetadata(outputFile);
            }
            
            Assert.That(File.Exists(outputPath));
            // Input file is 33 seconds long, seeking to the 30th second and then 
            // attempting to cut another 25 seconds isn't possible as there's only 3 seconds
            // of content length, so instead the library cuts the maximumum possible.
        }
        private static string GetThumbnail(MediaFile inputFile, MediaFile outputFile, ConversionOptions conversionOptions)
        {
            var commandBuilder = new StringBuilder();

            commandBuilder.AppendFormat(CultureInfo.InvariantCulture, " -ss {0} ", conversionOptions.Seek.GetValueOrDefault(TimeSpan.FromSeconds(1)).TotalSeconds);

            commandBuilder.AppendFormat(" -i \"{0}\" ", inputFile.Filename);
            commandBuilder.AppendFormat(" -vframes {0} ", 1);

            return commandBuilder.AppendFormat(" \"{0}\" ", outputFile.Filename).ToString();
        }
示例#4
0
        internal void Convert(String inputPath, String outputPath, VideoFomatsSupported videoFormat, ConversionOptions conversionOptions = null)
        {
            if (!Enum.GetNames(typeof(VideoFomatsSupported)).Cast<String>()
                .Any(vfs => vfs.Equals(System.IO.Path.GetExtension(inputPath.ToLower()).Substring(1))))
                throw new Exception("Format du fichier n'est pas supporté");

            _inputFilePath = inputPath;
            _outputFilePath = outputPath;
            _videoFormatsSupported = videoFormat;
            conversionOptions = conversionOptions ?? new ConversionOptions();
        }
示例#5
0
        /// -------------------------------------------------------------------------------------------------
        /// <summary>
        ///     <para> ---</para>
        ///     <para> Converts media with conversion options</para>
        /// </summary>
        /// <param name="inputFile">    Input file. </param>
        /// <param name="outputFile">   Output file. </param>
        /// <param name="options">      Conversion options. </param>
        public void Convert(MediaFile inputFile, MediaFile outputFile, ConversionOptions options)
        {
            EngineParameters engineParams = new EngineParameters
                {
                    InputFile = inputFile,
                    OutputFile = outputFile,
                    ConversionOptions = options,
                    Task = FFmpegTask.Convert
                };

            this.FFmpegEngine(engineParams);
        }
示例#6
0
        internal void Convert(String inputPath, String outputPath, AudioFomatsSupported audioFormat, ConversionOptions conversionOptions = null)
        {
            List<string> formats = new List<string>();
            formats.AddRange(Enum.GetNames(typeof(AudioFomatsSupported)).ToList());
            formats.AddRange(Enum.GetNames(typeof(VideoFomatsSupported)).ToList());

            if (!formats.Any(vfs => vfs.Equals(System.IO.Path.GetExtension(inputPath).ToLower().Substring(1))))
                            throw new Exception("Format du fichier n'est pas supporté");

            _inputFilePath = inputPath;
            _outputFilePath = outputPath;
            _audioFormatsSupported = audioFormat;
            conversionOptions = conversionOptions ?? new ConversionOptions();
        }
示例#7
0
        protected virtual void Convert(String inputFilepath,String outputFolder, ConversionOptions conversionOptions, bool convertToAudio)
        {
            if(String.IsNullOrWhiteSpace(FileName))
                FileName = Path.GetFileNameWithoutExtension(inputFilepath) + GetFormat(true);

            string outputFilePath = Path.Combine(outputFolder, FileName);
            MediaFile inputFile = new MediaFile(@inputFilepath);
            MediaFile outputFile = new MediaFile(outputFilePath);
            using (var engine = new Engine())
            {
                if (processStartingEventHandler != null)
                    processStartingEventHandler(this, EventArgs.Empty);
                engine.Convert(inputFile, outputFile);
                if (processCompletionEventHandler != null)
                    processCompletionEventHandler(this, EventArgs.Empty);

            }
        }
示例#8
0
        public static void ExtractFrame(string file, int momentFromStartInSeconds, string output)
        {
            var inputFile = new MediaFile { Filename = file };
            var outputFile = new MediaFile { Filename = output };

            using (var engine = new Engine())
            {
                engine.GetMetadata(inputFile);
                var options = new ConversionOptions { Seek = TimeSpan.FromSeconds(momentFromStartInSeconds) };
                try
                {
                    engine.GetThumbnail(inputFile, outputFile, options);
                }
                catch(Exception ex)
                {
                    Console.WriteLine("Failed to extract the image from: {0} because of {1}", inputFile, ex.ToString());
                }
            }
        }
示例#9
0
        public void Can_ConvertToDVD()
        {
            string outputPath = string.Format("{0}/Convert_DVD_Test.vob", Path.GetDirectoryName(_outputFilePath));

            var inputFile = new MediaFile { Filename = _inputFilePath };
            var outputFile = new MediaFile { Filename = outputPath };

            var conversionOptions = new ConversionOptions { Target = Target.DVD, TargetStandard = TargetStandard.PAL };

            using (var engine = new Engine())
            {
                engine.ConvertProgressEvent += engine_ConvertProgressEvent;
                engine.ConversionCompleteEvent += engine_ConversionCompleteEvent;

                engine.Convert(inputFile, outputFile, conversionOptions);

                engine.GetMetadata(inputFile);
                engine.GetMetadata(outputFile);
            }

            PrintMetadata(inputFile.Metadata);
            PrintMetadata(outputFile.Metadata);
        }
        private void CreateImageButton_Click(object sender, RoutedEventArgs e)
        {
            _imageExt.ToBitmapImage(Screen);

            ImageItem.Source = _imageExt.GetImageSource();

            var time = Screen.Position;

            var foo = new MediaFile {Filename = "Hist.bmp"};

            if (File.Exists("Hist.bmp"))
            {
                File.Delete("Hist.bmp");
            }

            using (var engine = new Engine())
            {
                engine.GetMetadata(inputFile);

                var options = new ConversionOptions {Seek = TimeSpan.FromMilliseconds(time.Milliseconds)};
                engine.GetThumbnail(inputFile, foo, options);
            }
        }
        private static ConversionOptions InitializeClippingData(decimal newDurationInMilliseconds, TrailerClipperOptions clipperOptions)
        {
            var options = new ConversionOptions();

            var newDuration = Convert.ToDouble(newDurationInMilliseconds);

            var newDurationTimeSpan = TimeSpan.FromMilliseconds(newDuration);

            var seekToPosition = TimeSpan.Zero;

            if (clipperOptions.RemoveIntro)
            {
                var introLength = Convert.ToDouble(clipperOptions.IntroLengthInMilliseconds);

                seekToPosition = TimeSpan.FromMilliseconds(introLength);
            }

            var lengthSpan = newDurationTimeSpan.Subtract(seekToPosition);

            options.CutMedia(seekToPosition, lengthSpan);

            return options;
        }
        public StdResult<List<string>> ExtractFrames(int nbFramesDesired)
        {
            DesiredFramesAmount = nbFramesDesired;
            int nbSeconds = (int)GetVideoLength().ReturnObject.TotalSeconds;
            int framePeriod = nbSeconds / (nbFramesDesired + 1);

            List<MediaFile> outputFiles = new List<MediaFile>();

            using (var engine = new Engine())
            {
                engine.GetMetadata(InputFile);

                for (int i = 0; i < DesiredFramesAmount; i++)
                {
                    outputFiles.Add(new MediaFile { Filename = string.Format(OutputSpriteFramePathTemplate, i) });
                    var options = new ConversionOptions { Seek = TimeSpan.FromSeconds((i + 1) * framePeriod), VideoSize = VideoSize._200par125 };
                    if (File.Exists(outputFiles[i].Filename))
                        File.Delete(outputFiles[i].Filename);
                    engine.GetThumbnail(InputFile, outputFiles[i], options);
                }
            }
            OutputSpriteFrames = outputFiles.Select(of => of.Filename).ToList();
            return StdResult<List<string>>.OkResultInstance(OutputSpriteFrames);
        }
示例#13
0
        public void Can_CropVideo()
        {
            string outputPath = string.Format(@"{0}\Crop_Video_Test.mp4", Path.GetDirectoryName(_outputFilePath));

            var inputFile = new MediaFile { Filename = _inputFilePath };
            var outputFile = new MediaFile { Filename = outputPath };

            using (var engine = new Engine())
            {
                engine.ConvertProgressEvent += engine_ConvertProgressEvent;
                engine.ConversionCompleteEvent += engine_ConversionCompleteEvent;

                engine.GetMetadata(inputFile);

                var options = new ConversionOptions();
                options.SourceCrop = new CropRectangle()
                {
                    X = 100,
                    Y = 100,
                    Width = 50,
                    Height = 50
                };

                engine.Convert(inputFile, outputFile, options);
            }
        }
示例#14
0
        /// <summary>
        ///     Retrieve a thumbnail image from a video file.
        /// </summary>
        /// <param name="inputFile">Video file</param>
        /// <param name="outputFile">Image file</param>
        /// <param name="options">Conversion options</param>
        public void GetThumbnail(MediaFile inputFile, MediaFile outputFile, ConversionOptions options)
        {
            var engineParams = new EngineParameters
            {
                InputFile = inputFile,
                OutputFile = outputFile,
                ConversionOptions = options,
                Task = FFmpegTask.GetThumbnail
            };

            FFmpegEngine(engineParams);
        }
示例#15
0
        public void Can_GetThumbnailFromHTTPLink()
        {
            string outputPath = string.Format(@"{0}\Get_Thumbnail_FromHTTP_Test.jpg", Path.GetDirectoryName(_outputFilePath));

            var inputFile = new MediaFile { Filename = _inputUrlPath };
            var outputFile = new MediaFile { Filename = outputPath };

            using (var engine = new Engine())
            {
                engine.ConvertProgressEvent += engine_ConvertProgressEvent;
                engine.ConversionCompleteEvent += engine_ConversionCompleteEvent;

                engine.GetMetadata(inputFile);

                var options = new ConversionOptions
                {
                    Seek = TimeSpan.FromSeconds(inputFile.Metadata.Duration.TotalSeconds / 2)
                };
                engine.GetThumbnail(inputFile, outputFile, options);
            }
        }
示例#16
0
        public void Can_GetThumbnail()
        {
            string outputPath = string.Format(@"{0}\Get_Thumbnail_Test.jpg", Path.GetDirectoryName(_outputFilePath));
            if (File.Exists(outputPath))
            {
                File.Delete(outputPath);
            }

            var inputFile = new MediaFile { Filename = _inputFilePath };
            var outputFile = new MediaFile { Filename = outputPath };
            var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
            var localMediaToolkitFfMpeg = Path.Combine(localAppData, "MediaToolkit", "ffmpeg.exe");

            using (var engine = new Engine(localMediaToolkitFfMpeg))
            {
                engine.ConvertProgressEvent += engine_ConvertProgressEvent;
                engine.ConversionCompleteEvent += engine_ConversionCompleteEvent;

                engine.GetMetadata(inputFile);

                var options = new ConversionOptions
                {
                    Seek = TimeSpan.FromSeconds(inputFile.Metadata.Duration.TotalSeconds / 2)
                };
                engine.GetThumbnail(inputFile, outputFile, options);
            }
            Assert.That(File.Exists(outputPath));
        }
示例#17
0
        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            var options = new MediaToolkit.Options.ConversionOptions();
            var inputFiled = new MediaFile { Filename = VideoToTrim };
            var outputFile = new MediaFile { Filename = VideoToTrimTo };

            string video2trim = "\"" + VideoToTrim + "\"";
            string video2trim2 = "\"" + VideoToTrimTo + "\"";
            using (var engine = new Engine())
            {
                engine.GetMetadata(inputFiled);
                options.CutMedia(Start, End);
                //fade=in:0:30
                engine.ConvertProgressEvent += ConvertProgressEvent;
                engine.ConversionCompleteEvent += engine_ConversionCompleteEvent;
                engine.Convert(inputFiled, outputFile, options);

                //ffmpeg -i input.mp4 -filter:v 'fade=in:0:50' \ -c:v libx264 -crf 22 -preset veryfast -c:a copy output.mp4
                //engine.CustomCommand("-ss " + Start + " -t " + End + " -i " + video2trim + " " + "\"" + " fade=in:0:03" + "\"" +  " " + video2trim2);
                //engine.CustomCommand("-ss " + Start + " -t " + End + " -i" + " " + video2trim + " -filter:v" + " fade=in=0:130 " + "-c:v libx264 -crf 22 -preset veryfast -c:a copy " + video2trim2);
                //std trim
               // string startTime = Start.Hours + ":" + Start.m
                //engine.CustomCommand("-ss " + Start. + " -t " + End + " -i " + video2trim + " -acodec copy -vcodec copy " + video2trim2);
            }
        }
示例#18
0
        public static void IntroVideoss(string VideoFile)
        {
            // this.FileName = VideoFile;

            var inputFile = new MediaFile { Filename = VideoFile };
            var outputFile = new MediaFile {Filename = @"Z:\ddd.mp4"};
            var inputFiles = new MediaToolkit.Options.ConversionOptions();

            var engine = new MediaToolkit.Engine();

            TimeSpan t = new TimeSpan(0, 0, 2, 10, 49);
            TimeSpan d = new TimeSpan(0, 0, inputFile.Metadata.Duration.Minutes, inputFile.Metadata.Duration.Seconds, inputFile.Metadata.Duration.Milliseconds);
            d = inputFile.Metadata.Duration;
             d = d - t;

             inputFiles.CutMedia (t, d);
             engine.Convert(inputFile, outputFile, inputFiles);
        }
        private static string Convert(MediaFile inputFile, MediaFile outputFile, ConversionOptions conversionOptions)
        {
            var commandBuilder = new StringBuilder();

            // Default conversion
            if (conversionOptions == null)
                return commandBuilder.AppendFormat(" -i \"{0}\"  \"{1}\" ", inputFile.Filename, outputFile.Filename).ToString();

            // Media seek position
            if (conversionOptions.Seek != null)
                commandBuilder.AppendFormat(CultureInfo.InvariantCulture, " -ss {0} ", conversionOptions.Seek.Value.TotalSeconds);

            commandBuilder.AppendFormat(" -i \"{0}\" ", inputFile.Filename);

            // Physical media conversion (DVD etc)
            if (conversionOptions.Target != Target.Default)
            {
                commandBuilder.Append(" -target ");
                if (conversionOptions.TargetStandard != TargetStandard.Default)
                {
                    commandBuilder.AppendFormat(" {0}-{1} \"{2}\" ", conversionOptions.TargetStandard.ToLower(), conversionOptions.Target.ToLower(), outputFile.Filename);

                    return commandBuilder.ToString();
                }
                commandBuilder.AppendFormat("{0} \"{1}\" ", conversionOptions.Target.ToLower(), outputFile.Filename);

                return commandBuilder.ToString();
            }

            // Audio sample rate
            if (conversionOptions.AudioSampleRate != AudioSampleRate.Default)
                commandBuilder.AppendFormat(" -ar {0} ", conversionOptions.AudioSampleRate.Remove("Hz"));

            // Maximum video duration
            if (conversionOptions.MaxVideoDuration != null)
                commandBuilder.AppendFormat(" -t {0} ", conversionOptions.MaxVideoDuration);

            // Video bit rate
            if (conversionOptions.VideoBitRate != null)
                commandBuilder.AppendFormat(" -b {0}k ", conversionOptions.VideoBitRate);

            // Video size / resolution
            if (conversionOptions.VideoSize == VideoSize.Custom)
            {
                commandBuilder.AppendFormat(" -vf \"scale={0}:{1}\" ", conversionOptions.CustomWidth ?? -2, conversionOptions.CustomHeight ?? -2);
            }
            else if (conversionOptions.VideoSize != VideoSize.Default)
            {
                string size = conversionOptions.VideoSize.ToLower();
                if (size.StartsWith("_")) size = size.Replace("_", "");
                if (size.Contains("_")) size = size.Replace("_", "-");

                commandBuilder.AppendFormat(" -s {0} ", size);
            }

            // Video aspect ratio
            if (conversionOptions.VideoAspectRatio != VideoAspectRatio.Default)
            {
                string ratio = conversionOptions.VideoAspectRatio.ToString();
                ratio = ratio.Substring(1);
                ratio = ratio.Replace("_", ":");

                commandBuilder.AppendFormat(" -aspect {0} ", ratio);
            }

            // Video cropping
            if (conversionOptions.SourceCrop != null)
            {
                var crop = conversionOptions.SourceCrop;
                commandBuilder.AppendFormat(" -filter:v \"crop={0}:{1}:{2}:{3}\" ", crop.Width, crop.Height, crop.X, crop.Y);
            }

            if (conversionOptions.BaselineProfile)
            {
                commandBuilder.Append(" -profile:v baseline ");
            }

            return commandBuilder.AppendFormat(" \"{0}\" ", outputFile.Filename).ToString();
        }
示例#20
0
 public void genThumb()
 {
     thumbPath = System.IO.Path.Combine( System.IO.Path.GetTempPath(), cutName+index.ToString()+".jpg");
     var inputFile = new MediaFile { Filename = sourcePath };
     var outputFile = new MediaFile { Filename = thumbPath };
     using (var engine = new Engine())
     {
         engine.GetMetadata(inputFile);
         var options = new ConversionOptions { Seek = startTime };
         engine.GetThumbnail(inputFile, outputFile, options);
     }
     var img = System.Drawing.Image.FromFile(thumbPath);
     MemoryStream ms = new MemoryStream();
     img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
     imgThumb = ms.ToArray();
 }
        public StdResult<string> CreateThumbnail(string forceOutputFilePath = null, TimeSpan? forceTimeSpan = null)
        {
            var outputFile = new MediaFile { Filename = OutputImagePath };

            using (var engine = new Engine())
            {
                engine.GetMetadata(InputFile);

                // Saves the frame located on the 15th second of the video.
                var options = new ConversionOptions { Seek = TimeSpan.FromSeconds(15) };
                engine.GetThumbnail(InputFile, outputFile, options);
            }
            return StdResult<string>.OkResultInstance(OutputImagePath);
        }
示例#22
0
        private static string GetThumbnail(MediaFile inputFile, MediaFile outputFile, ConversionOptions conversionOptions)
        {
            var commandBuilder = new StringBuilder();

            commandBuilder.AppendFormat(" -ss {0} ",
                conversionOptions.Seek.GetValueOrDefault(TimeSpan.FromSeconds(1)).TotalSeconds);

            commandBuilder.AppendFormat(" -i \"{0}\" ", inputFile.Filename);
            commandBuilder.AppendFormat(" -t {0} ", 1);
            commandBuilder.AppendFormat(" -vframes {0} ", 1);

            // Video size / resolution
            if (conversionOptions.VideoSize != VideoSize.Default)
            {
                string size = conversionOptions.VideoSize.ToLower();
                if (size.StartsWith("_")) size = size.Replace("_", "");
                if (size.Contains("_")) size = size.Replace("_", "-");
                if (size.Contains("par")) size = size.Replace("par", "*");

                commandBuilder.AppendFormat(" -s {0} ", size);
            }

            return commandBuilder.AppendFormat(" \"{0}\" ", outputFile.Filename).ToString();
        }
示例#23
0
        private static string Convert(MediaFile inputFile, MediaFile outputFile, ConversionOptions conversionOptions)
        {
            var commandBuilder = new StringBuilder();

            // Default conversion
            if (conversionOptions == null)
                return commandBuilder.AppendFormat(" -i \"{0}\"  \"{1}\" ",inputFile.Filename, outputFile.Filename).ToString();

            // Media seek position
            if (conversionOptions.Seek != null)
                commandBuilder.AppendFormat(" -ss {0} ", conversionOptions.Seek.Value.TotalSeconds);

            commandBuilder.AppendFormat(" -i \"{0}\" ", inputFile.Filename);

            // Physical media conversion (DVD etc)
            if (conversionOptions.Target != Target.Default)
            {
                commandBuilder.Append(" -target ");
                if (conversionOptions.TargetStandard != TargetStandard.Default)
                {
                    commandBuilder.AppendFormat(" {0}-{1} \"{2}\" ", conversionOptions.TargetStandard.ToLower(),
                        conversionOptions.Target.ToLower(), outputFile.Filename);

                    return commandBuilder.ToString();
                }
                commandBuilder.AppendFormat("{0} \"{1}\" ", conversionOptions.Target.ToLower(), outputFile.Filename);

                return commandBuilder.ToString();
            }

            // Audio sample rate
            if (conversionOptions.AudioSampleRate != AudioSampleRate.Default)
                commandBuilder.AppendFormat(" -ar {0} ", conversionOptions.AudioSampleRate.Remove("Hz"));

            // Maximum video duration
            if (conversionOptions.MaxVideoDuration != null)
                commandBuilder.AppendFormat(" -t {0} ", conversionOptions.MaxVideoDuration);

            // Video bit rate
            if (conversionOptions.VideoBitRate != null)
                commandBuilder.AppendFormat(" -b {0}k ", conversionOptions.VideoBitRate);

            // Video size / resolution
            if (conversionOptions.VideoSize != VideoSize.Default)
            {
                string size = conversionOptions.VideoSize.ToLower();
                if (size.StartsWith("_")) size = size.Replace("_", "");
                if (size.Contains("_")) size = size.Replace("_", "-");

                commandBuilder.AppendFormat(" -s {0} ", size);
            }

            // Video aspect ratio
            if (conversionOptions.VideoAspectRatio != VideoAspectRatio.Default)
            {
                string ratio = conversionOptions.VideoAspectRatio.ToString();
                ratio = ratio.Substring(1);
                ratio = ratio.Replace("_", ":");

                commandBuilder.AppendFormat(" -aspect {0} ", ratio);
            }

            return commandBuilder.AppendFormat(" \"{0}\" ", outputFile.Filename).ToString();
        }
示例#24
0
        public void Can_CutVideo()
        {
            string outputPath = string.Format(@"{0}\Cut_Video_Test.mp4", Path.GetDirectoryName(_outputFilePath));

            var inputFile = new MediaFile { Filename = _inputFilePath };
            var outputFile = new MediaFile { Filename = outputPath };

            using (var engine = new Engine())
            {
                engine.ConvertProgressEvent += engine_ConvertProgressEvent;
                engine.ConversionCompleteEvent += engine_ConversionCompleteEvent;

                engine.GetMetadata(inputFile);

                var options = new ConversionOptions();
                options.CutMedia(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(25));

                engine.Convert(inputFile, outputFile, options);
            }
        }
示例#25
-1
        public IEnumerable<MediaSegment> Segment(FileInfo file, long fileId)
        {
            var source = new MediaFile(file.FullName);
            using (var engine = new Engine())
            {
                engine.GetMetadata(source);
                var progressMs = 0.0;
                while (progressMs < source.Metadata.Duration.TotalMilliseconds)
                {
                    var options = new ConversionOptions();
                    var endMs = Math.Min(progressMs + _segmentLengthMs, source.Metadata.Duration.TotalMilliseconds);

                    options.CutMedia(TimeSpan.FromMilliseconds(progressMs),
                        TimeSpan.FromMilliseconds(endMs));

                    var outputFile = Path.Combine(file.DirectoryName,
                        string.Format("{0}_audio_{1}ms.wav", file.Name, progressMs));

                    engine.Convert(source, new MediaFile(outputFile), options);
                    yield return new MediaSegment
                    {
                        FileId = fileId,
                        File = new FileInfo(outputFile),
                        OffsetMs = progressMs,
                        DurationMs = endMs - progressMs
                    };
                    progressMs = endMs;
                }
            }
        }