private static void Start() { for (int i = 0; i < VideoSettings.NbSpriteDaemon; i++) { Task daemon = Task.Run(() => { while (true) { FileItem fileItem = null; try { Thread.Sleep(1000); fileItem = null; if (!queueFileItems.TryDequeue(out fileItem)) { continue; } CurrentPositionInQueue++; // si le client a pas demandé le progress depuis plus de 20s, annuler l'opération if ((DateTime.UtcNow - fileItem.FileContainer.LastTimeProgressRequested).TotalSeconds > FrontSettings.MaxGetProgressCanceled) { fileItem.EncodeErrorMessage = "Canceled"; fileItem.EncodeProgress = null; fileItem.IpfsErrorMessage = "Canceled"; fileItem.IpfsProgress = null; LogManager.AddSpriteMessage("SourceFileName " + Path.GetFileName(fileItem.FileContainer.SourceFileItem.FilePath) + " car dernier getProgress a dépassé 20s", "Annulation"); fileItem.CleanFiles(); } else { // sprite creation video if (SpriteManager.Encode(fileItem)) { IpfsDaemon.Queue(fileItem); } } } catch (Exception ex) { LogManager.AddSpriteMessage(ex.ToString(), "Exception non gérée"); fileItem.EncodeErrorMessage = "Exception non gérée"; fileItem.CleanFiles(); } } }); daemons.Add(daemon); } }
private static void Log(string message, string typeMessage, bool spriteMode) { if (spriteMode) { LogManager.AddSpriteMessage(message, typeMessage); } else { LogManager.AddEncodingMessage(message, typeMessage); } }
protected override void ProcessItem(FileItem fileItem) { // si le client a pas demandé le progress depuis plus de 20s, annuler l'opération if (!fileItem.SpriteEncodeProcess.CanProcess()) { string message = "FileName " + Path.GetFileName(fileItem.OutputFilePath) + " car le client est déconnecté"; LogManager.AddSpriteMessage(message, "Annulation"); fileItem.SpriteEncodeProcess.CancelCascade("Le client est déconnecté."); return; } // sprite creation video if (SpriteManager.Encode(fileItem)) { IpfsDaemon.Instance.Queue(fileItem); } }
public void StartProcess(string arguments, int timeout) { var processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = "ffmpeg"; processStartInfo.RedirectStandardError = true; processStartInfo.WorkingDirectory = TempFileManager.GetTempDirectory(); processStartInfo.UseShellExecute = false; processStartInfo.ErrorDialog = false; processStartInfo.CreateNoWindow = true; processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; processStartInfo.Arguments = arguments; if (_fileItem.TypeFile == TypeFile.SpriteVideo) { LogManager.AddSpriteMessage(processStartInfo.FileName + " " + processStartInfo.Arguments, "Launch command"); } else { LogManager.AddEncodingMessage(processStartInfo.FileName + " " + processStartInfo.Arguments, "Launch command"); } using (Process process = Process.Start(processStartInfo)) { process.ErrorDataReceived += new DataReceivedEventHandler(ErrorDataReceived); process.BeginErrorReadLine(); bool success = process.WaitForExit(timeout); if (!success) { throw new InvalidOperationException("Timeout : Le fichier n'a pas pu être encodé dans le temps imparti."); } if (process.ExitCode != 0) { throw new InvalidOperationException($"Le fichier n'a pas pu être encodé, erreur {process.ExitCode}."); } } }
public static bool Encode(FileItem fileItem) { FileItem sourceFile = fileItem.FileContainer.SourceFileItem; try { fileItem.SpriteEncodeProcess.StartProcessDateTime(); LogManager.AddSpriteMessage(LogLevel.Information, "SourceFilePath " + Path.GetFileName(fileItem.SourceFilePath), "Start Sprite"); int nbImages = VideoSettings.Instance.NbSpriteImages; int heightSprite = VideoSettings.Instance.HeightSpriteImages; // Calculer nb image/s // si < 100s de vidéo -> 1 image/s // sinon (nb secondes de la vidéo / 100) image/s string frameRate = "1"; int duration = sourceFile.VideoDuration.Value; if (duration > nbImages) { frameRate = $"{nbImages}/{duration}"; //frameRate = inverse de image/s } int spriteWidth = SizeHelper.GetWidth(sourceFile.VideoWidth.Value, sourceFile.VideoHeight.Value, heightSprite); string sizeImageMax = $"scale={spriteWidth}:{heightSprite}"; // Extract frameRate image/s de la video string arguments = $"-y -i {Path.GetFileName(fileItem.SourceFilePath)} -r {frameRate} -vf {sizeImageMax} -f image2 {GetPattern(fileItem.TempFilePath)}"; var ffmpegProcessManager = new FfmpegProcessManager(fileItem, fileItem.SpriteEncodeProcess); ffmpegProcessManager.StartProcess(arguments, VideoSettings.Instance.EncodeGetImagesTimeout); IList <string> files = GetListImageFrom(fileItem.TempFilePath); // récupération des images LogManager.AddSpriteMessage(LogLevel.Information, (files.Count - 1) + " images", "Start Combine images"); // garder que les 100 dernières images pour éliminer les premières (1 ou 2 en réalité) int skip = files.Count > VideoSettings.Instance.NbSpriteImages ? files.Count - VideoSettings.Instance.NbSpriteImages : 0; var list = new StringBuilder(); foreach (string imagePath in files.Skip(skip)) { if (list.Length > 0) { list.Append(" "); } list.Append(Path.GetFileName(imagePath)); } arguments = $"montage -mode concatenate -tile 1x {list} {Path.GetFileName(fileItem.TempFilePath)}"; var process = new ProcessManager(Path.Combine(GeneralSettings.Instance.ImageMagickPath, "magick"), arguments, LogManager.SpriteLogger); bool successSprite = process.Launch(5); TempFileManager.SafeDeleteTempFiles(files); // suppression des images if (!successSprite) { fileItem.SpriteEncodeProcess.SetErrorMessage("Error while combine images", "Error creation sprite while combine images"); return(false); } fileItem.ReplaceOutputPathWithTempPath(); LogManager.AddSpriteMessage(LogLevel.Information, "OutputFileName " + Path.GetFileName(fileItem.OutputFilePath) + " / FileSize " + fileItem.FileSize, "End Sprite"); fileItem.SpriteEncodeProcess.EndProcessDateTime(); return(true); } catch (Exception ex) { string message = "Video Duration " + sourceFile.VideoDuration + " / FileSize " + fileItem.FileSize + " / Progress " + fileItem.SpriteEncodeProcess.Progress; fileItem.SpriteEncodeProcess.SetErrorMessage("Exception non gérée", message, ex); IList <string> files = GetListImageFrom(fileItem.TempFilePath); // récupération des images TempFileManager.SafeDeleteTempFiles(files); // suppression des images return(false); } }
public static bool Encode(FileItem fileItem) { FileItem sourceFile = fileItem.FileContainer.SourceFileItem; try { fileItem.SpriteEncodeProcess.StartProcessDateTime(); LogManager.AddSpriteMessage("SourceFilePath " + Path.GetFileName(fileItem.SourceFilePath), "Start Sprite"); // Récupérer la durée totale de la vidéo et sa résolution, autorisation sprite creation if (!VideoSourceManager.SuccessAnalyseSource(fileItem, true, fileItem.SpriteEncodeProcess)) { return(false); } int nbImages = VideoSettings.NbSpriteImages; int heightSprite = VideoSettings.HeightSpriteImages; // Calculer nb image/s // si < 100s de vidéo -> 1 image/s // sinon (nb secondes de la vidéo / 100) image/s string frameRate = "1"; int duration = sourceFile.VideoDuration.Value; if (duration > nbImages) { frameRate = $"{nbImages}/{duration}"; //frameRate = inverse de image/s } int spriteWidth = SizeHelper.GetWidth(sourceFile.VideoWidth.Value, sourceFile.VideoHeight.Value, heightSprite); string sizeImageMax = $"scale={spriteWidth}:{heightSprite}"; // Extract frameRate image/s de la video string arguments = $"-y -i {Path.GetFileName(fileItem.SourceFilePath)} -r {frameRate} -vf {sizeImageMax} -f image2 {GetPattern(fileItem.TempFilePath)}"; var ffmpegProcessManager = new FfmpegProcessManager(fileItem, fileItem.SpriteEncodeProcess); ffmpegProcessManager.StartProcess(arguments, VideoSettings.EncodeGetImagesTimeout); string[] files = GetListImageFrom(fileItem.TempFilePath); // récupération des images LogManager.AddSpriteMessage((files.Length - 1) + " images", "Start Combine images"); bool successSprite = CombineBitmap(files.Skip(files.Length - VideoSettings.NbSpriteImages).ToArray(), fileItem.TempFilePath); // création du sprite TempFileManager.SafeDeleteTempFiles(files); // suppression des images if (successSprite) { fileItem.SetOutputFilePath(fileItem.TempFilePath); LogManager.AddSpriteMessage("OutputFileName " + Path.GetFileName(fileItem.OutputFilePath) + " / FileSize " + fileItem.FileSize, "End Sprite"); } else { LogManager.AddSpriteMessage("Error while combine images", "Error"); fileItem.SpriteEncodeProcess.SetErrorMessage("Error creation sprite while combine images"); return(false); } fileItem.SpriteEncodeProcess.EndProcessDateTime(); return(true); } catch (Exception ex) { LogManager.AddSpriteMessage("Video Duration " + sourceFile.VideoDuration + " / FileSize " + fileItem.FileSize + " / Progress " + fileItem.SpriteEncodeProcess.Progress + " / Exception : " + ex, "Exception"); fileItem.SpriteEncodeProcess.SetErrorMessage("Exception"); string[] files = GetListImageFrom(fileItem.TempFilePath); // récupération des images TempFileManager.SafeDeleteTempFiles(files); // suppression des images return(false); } }
private static bool CombineBitmap(string[] filesToCombine, string outputFilePath) { if (filesToCombine == null || filesToCombine.Length == 0) { return(false); } if (string.IsNullOrWhiteSpace(outputFilePath)) { return(false); } //read all images into memory var images = new List <Image>(); try { int width = 0; int height = 0; foreach (string imagePath in filesToCombine) { // create a Bitmap from the file and add it to the list Image image = Image.FromFile(imagePath); // update the size of the final bitmap height += image.Height; width = image.Width > width ? image.Width : width; images.Add(image); } //create a bitmap to hold the combined image using (var finalBitmap = new Bitmap(width, height)) { //get a graphics object from the image so we can draw on it using (Graphics graphics = Graphics.FromImage(finalBitmap)) { // Ajoute les images les unes à la suite des autres verticalement int offset = 0; foreach (Image image in images) { graphics.DrawImage(image, new Rectangle(0, offset, image.Width, image.Height)); offset += image.Height; } } finalBitmap.Save(outputFilePath, ImageFormat.Jpeg); } return(true); } catch (Exception ex) { LogManager.AddSpriteMessage(ex.ToString(), "Exception"); TempFileManager.SafeDeleteTempFile(outputFilePath); return(false); } finally { try { //clean up memory foreach (Image image in images) { image.Dispose(); } } catch {} } }
protected override void LogException(FileItem fileItem, Exception ex) { LogManager.AddSpriteMessage(ex.ToString(), "Exception non gérée"); fileItem.SpriteEncodeProcess.SetErrorMessage("Exception non gérée"); }