Beispiel #1
0
            public string Save(string videoName, string overlayTextMarking, EHorizontalAlign markingHorizontalAlign, EVerticalAlign markingVerticalAlign, double?durationMini = null)
            {
                this.TraceDebug($"Saving video \"{videoName}\" in buffer");

                var videoFileName = $"{videoName}.mpeg";

                var exeFilePath = Path.Combine(
                    Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                    @"Video\",
                    Environment.Is64BitOperatingSystem ? "videosplitter-64.exe" : "videosplitter-32.exe");
                var fontFilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                                                @"Video\", "arial.ttf");
                var textFilePath = Path.GetTempFileName();

                if (!string.IsNullOrWhiteSpace(overlayTextMarking))
                {
                    using (var stream = File.OpenWrite(textFilePath))
                        using (var writer = new StreamWriter(stream, new UTF8Encoding(false)))
                        {
                            writer.Write(overlayTextMarking.Replace(@"\", @"\\"));
                        }
                }

                string markingAlignment = string.Empty;

                switch (markingHorizontalAlign)
                {
                case EHorizontalAlign.Center:
                    markingAlignment = $"x=(w-tw)/2";
                    break;

                case EHorizontalAlign.Left:
                    markingAlignment = $"x={_MARKING_PADDING}";
                    break;

                case EHorizontalAlign.Right:
                    markingAlignment = $"x=w-tw-{_MARKING_PADDING}";
                    break;
                }

                switch (markingVerticalAlign)
                {
                case EVerticalAlign.Bottom:
                    markingAlignment += $":y=h-th-{_MARKING_PADDING}";
                    break;

                case EVerticalAlign.Center:
                    markingAlignment += $":y=(h-th)/2";
                    break;

                case EVerticalAlign.Top:
                    markingAlignment += $":y={_MARKING_PADDING}";
                    break;
                }

                double speed      = 1;
                bool   slowMotion = false;

                if (durationMini != null && Duration.TotalSeconds < durationMini)
                {
                    slowMotion = true;
                    speed      = Duration.TotalMilliseconds / (durationMini.Value * 1000);
                }
                List <string> filters = new List <string>();

                if (slowMotion)
                {
                    filters.Add($"setpts=(1/{speed.ToString().Replace(',', '.')})*PTS");
                }
                if (!string.IsNullOrWhiteSpace(overlayTextMarking))
                {
                    string formattedFontFilePath = fontFilePath.Replace(@"\", @"\\").Replace(":", @"\:");
                    string formattedtextFilePath = textFilePath.Replace(@"\", @"\\").Replace(":", @"\:");
                    filters.Add($"drawtext=fontfile='{formattedFontFilePath}':textfile='{formattedtextFilePath}':fontcolor=white:fontsize=24:box=1:[email protected]:boxborderw=5:{markingAlignment}");
                }

                var processArgumentsBuilder = new StringBuilder("-y -nostdin");

                processArgumentsBuilder.Append($" -ss {From.ToString(@"hh\:mm\:ss")}.{From.Milliseconds}");
                processArgumentsBuilder.Append($" -t {Duration.ToString(@"hh\:mm\:ss")}.{Math.Max(Duration.Milliseconds, 200)}");
                processArgumentsBuilder.Append($" -i \"{_input}\"");
                if (filters.Count > 0)
                {
                    if (slowMotion)
                    {
                        processArgumentsBuilder.Append(" -an");
                    }
                    processArgumentsBuilder.Append($" -vf \"{string.Join(",", filters)}\"");
                }
                processArgumentsBuilder.Append($" -vcodec mpeg1video -b:v 4000k \"{videoFileName}\"");

                using (var process = new Process())
                {
                    process.StartInfo.FileName               = exeFilePath;
                    process.StartInfo.Arguments              = processArgumentsBuilder.ToString();
                    process.StartInfo.CreateNoWindow         = true;
                    process.StartInfo.UseShellExecute        = false;
                    process.StartInfo.RedirectStandardError  = true;
                    process.StartInfo.RedirectStandardOutput = true;

                    this.TraceDebug($"{exeFilePath} {processArgumentsBuilder}");

                    try
                    {
                        string errorOutput    = null;
                        string standardOutput = null;

                        process.Start();

                        var outputStreamTasks = new[]
                        {
                            Task.Factory.StartNew(() => errorOutput    = process.StandardError.ReadToEnd()),
                            Task.Factory.StartNew(() => standardOutput = process.StandardOutput.ReadToEnd())
                        };

                        var timeout = TimeSpan.FromMinutes(3); // TODO add to configuration
                        process.WaitForExit((int)timeout.TotalMilliseconds);
                        Task.WaitAll(outputStreamTasks, (int)timeout.TotalMilliseconds, KprocessExportWindow.CancellationToken);

                        this.TraceDebug(standardOutput);
                        Debug.WriteLine(standardOutput);

                        if (!string.IsNullOrWhiteSpace(errorOutput))
                        {
                            this.TraceError("Des erreurs ont été levées par le processus permettant de splitter les videos:");
                            this.TraceError(errorOutput);
                            Debug.WriteLine(errorOutput);
                        }
                    }
                    catch (Win32Exception e)
                    {
                        this.TraceError(e, "Le splitter de video n'a pas été trouvé");
                        throw new Exception("An issue has occured during video packaging. It seems that some components are missing.", e);
                    }
                    catch (OperationCanceledException e)
                    {
                        this.TraceError(e, "L'export a été annulé lors du split des vidéos");
                        throw;
                    }
                    catch (Exception e)
                    {
                        this.TraceError(e, "Une erreur non prévue s'est produite lors du split de la video");
                        throw;
                    }
                    finally
                    {
                        try
                        {
                            File.Delete(textFilePath);
                        }
                        catch { }
                    }
                }

                return(videoName);
            }
        /// <summary>
        /// Стандартный конструктор
        /// </summary>
        /// <param name="parDepth">Глубина</param>
        /// <param name="parX">Координата X</param>
        /// <param name="parY">Координата Y</param>
        /// <param name="parStringToRender">Текстовая строка</param>
        /// <param name="parFont">Шрифт</param>
        /// <param name="parColor">Цвет</param>
        /// <param name="parScaleX">Масштабирование по X</param>
        /// <param name="parScaleY">Масштабирование по Y</param>
        /// <param name="parHAlign">Горизонтальное выравнивание</param>
        /// <param name="parVAlign">Вертикальное выравнивание</param>
        public RenderingString(double parDepth, double parX, double parY, string parStringToRender, SubassetDataFont parFont,
                               Color parColor, double parScaleX = 1.0, double parScaleY = 1.0, EHorizontalAlign parHAlign = EHorizontalAlign.Left,
                               EVerticalAlign parVAlign         = EVerticalAlign.Top)
        {
            LinkedList <SubassetDataSprite> usedSprites = parFont.GetSymbolsSprites(parStringToRender);

            SpritesToRender = new LinkedList <RenderingSprite>();

            double totalWidth  = 0;
            double totalHeight = 0;

            foreach (var usedSprite in usedSprites)
            {
                totalWidth += usedSprite.Width;
                if (usedSprite.Height > totalHeight)
                {
                    totalHeight = usedSprite.Height;
                }
            }

            X = OpenGlUtil.GetLeftXCoordBasedOnHorizontalAlign(parX, totalWidth, parHAlign, parScaleX);
            Y = OpenGlUtil.GetTopYCoordBasedOnVerticalAlign(parY, totalHeight, parVAlign, parScaleY);

            totalWidth = 0;
            //totalHeight = 0;
            foreach (var usedSprite in usedSprites)
            {
                SpritesToRender.AddLast(new RenderingSprite(usedSprite, X + totalWidth, Y, 0, parColor,
                                                            parDepth, parScaleX, parScaleY, EHorizontalAlign.Left, EVerticalAlign.Top));

                totalWidth += usedSprite.Width * parScaleX;
            }

            Depth = parDepth;
        }
        /// <summary>
        /// Получить координату X в пространстве OpenGL с учетом выбранного горизонтального выравнивания
        /// </summary>
        /// <param name="parX">X в обычной системе координат</param>
        /// <param name="parWidth">Ширина</param>
        /// <param name="parHAlign">Выбранное горизонтальное выравнивание</param>
        /// <param name="parScale">Величина масштабирования</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException">Неподдерживаемый формат выравнивания</exception>
        public static double GetLeftXCoordBasedOnHorizontalAlign(double parX, double parWidth, EHorizontalAlign parHAlign,
                                                                 double parScale)
        {
            switch (parHAlign)
            {
            case EHorizontalAlign.Left:
                return(parX);

                break;

            case EHorizontalAlign.Middle:
                return(parX - (parWidth * parScale / 2));

                break;

            case EHorizontalAlign.Right:
                return(parX - (parWidth * parScale));

                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(parHAlign), parHAlign, null);
            }
        }
        /// <summary>
        /// Стандартный конструктор
        /// </summary>
        /// <param name="parSprite">Производный ассет спрайта</param>
        /// <param name="parX">Координата X</param>
        /// <param name="parY">Координата Y</param>
        /// <param name="parRotationDegrees">Поворот в градусах</param>
        /// <param name="parBlendColor">Цвет</param>
        /// <param name="parDepth">Глубина</param>
        /// <param name="parScaleX">Масштабирование по X</param>
        /// <param name="parScaleY">Масштабирование по Y</param>
        /// <param name="parHAlign">Горизонтальное выравнивание</param>
        /// <param name="parVAlign">Вертикальное выравнивание</param>
        /// <param name="parRotationPivotX">Точка опоры для поворота, координата X</param>
        /// <param name="parRotationPivotY">Точка опоры для поворота, координата Y</param>
        public RenderingSprite(SubassetDataSprite parSprite, double parX, double parY, double parRotationDegrees, Color parBlendColor,
                               double parDepth,
                               double parScaleX         = 1.0, double parScaleY = 1.0, EHorizontalAlign parHAlign = EHorizontalAlign.Left,
                               EVerticalAlign parVAlign = EVerticalAlign.Top, double parRotationPivotX = 0, double parRotationPivotY = 0)
        {
            Sprite = parSprite;

            X = OpenGlUtil.GetLeftXCoordBasedOnHorizontalAlign(parX, parSprite.Width, parHAlign, parScaleX);
            Y = OpenGlUtil.GetTopYCoordBasedOnVerticalAlign(parY, parSprite.Height, parVAlign, parScaleY);

            Depth           = parDepth;
            RotationDegrees = parRotationDegrees;
            BlendColor      = parBlendColor;
            ScaleX          = parScaleX;
            ScaleY          = parScaleY;
            PivotX          = parRotationPivotX;
            PivotY          = parRotationPivotY;
        }