/// <summary>
        /// Transcode's all videos of a site
        /// </summary>
        /// <param name="configuration">Json configuration of IDBrowserService as IDBrowserConfiguration class</param>
        /// <param name="cancellationToken">CancellationToken</param>
        /// <param name="siteName">Site name to transcode</param>
        /// <param name="videoSize">Video size to transcode. (e.g. Hd480, Hd720, Hd1080)</param>
        /// <param name="taskCount">FFmpeg task count (Default 2)</param>
        /// <param name="logLevel">Serilog log level</param>
        public static void TranscodeAllVideos(IDBrowserConfiguration configuration, CancellationToken cancellationToken,
                                              string siteName, string videoSize, Serilog.Events.LogEventLevel logLevel, int taskCount)
        {
            LoggingLevelSwitch loggingLevelSwitch = new LoggingLevelSwitch
            {
                MinimumLevel = logLevel
            };

            Log.Logger = new LoggerConfiguration()
                         .MinimumLevel.ControlledBy(loggingLevelSwitch)
                         .WriteTo.File(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log", "ConsoleFunctions.log"))
                         .CreateLogger();

            SiteSettings siteSettings = configuration.Sites[siteName];

            IDImagerDB db = new IDImagerDB(GetIDImagerDBOptionsBuilder <IDImagerDB>(siteSettings.ConnectionStrings.DBType,
                                                                                    siteSettings.ConnectionStrings.IDImager).Options);

            var query = db.idCatalogItem
                        .Include(x => x.idFilePath)
                        .Where(x => configuration.VideoFileExtensions.Contains(x.idFileType));

            ProgressTaskFactory progressTaskFactory = new ProgressTaskFactory(taskCount, 100, 60, Log.Logger);

            Task windowChangeListenerTask = new Task(() =>
            {
                int width  = Console.WindowWidth;
                int height = Console.WindowHeight;

                while (!cancellationToken.IsCancellationRequested)
                {
                    if (width != Console.WindowWidth || height != Console.WindowHeight)
                    {
                        width  = Console.WindowWidth;
                        height = Console.WindowHeight;

                        progressTaskFactory.RedrawConsoleWindows(100, 60);
                    }

                    cancellationToken.WaitHandle.WaitOne(100);
                }
            }, cancellationToken);

            windowChangeListenerTask.Start();

            if (!IsWindows)
            {
                // Log output scrolling not supported at the moment because Console.MoveBufferArea is currently not supported under Linux and MacOs.
                // But we can write a single infoline.
                progressTaskFactory.WriteLog("Log output in console not supported under Linux at the moment. Please take a look at the ConsoleFunctions.log in Logs directory.",
                                             true, LogEventLevel.Information);
            }

            List <TranscodeVideoBatchInfo> listTranscodeVideoBatch = new List <TranscodeVideoBatchInfo>();

            foreach (idCatalogItem catalogItem in query)
            {
                catalogItem.GetHeightAndWidth(out int originalVideoWidth, out int originalVideoHeight);

                string strTranscodeFilePath = StaticFunctions.GetTranscodeFilePath(catalogItem.GUID,
                                                                                   siteSettings.ServiceSettings.TranscodeDirectory, videoSize);
                FileInfo transcodeFileInfo = new FileInfo(strTranscodeFilePath);

                if (!transcodeFileInfo.Exists)
                {
                    string strOriginalFilePath = StaticFunctions.GetImageFilePath(catalogItem, siteSettings.ServiceSettings.FilePathReplace);

                    TranscodeVideoBatchInfo transcodeVideoBatchInfo = new TranscodeVideoBatchInfo(catalogItem.GUID, originalVideoWidth, originalVideoHeight,
                                                                                                  strOriginalFilePath, strTranscodeFilePath);

                    listTranscodeVideoBatch.Add(transcodeVideoBatchInfo);
                }
            }

            db.Dispose();

            int intTotalCount = listTranscodeVideoBatch.Count();
            int intCounter    = 1;
            TranscodeVideoBatchInfo lastTranscodeVideoBatch = listTranscodeVideoBatch.LastOrDefault();

            foreach (TranscodeVideoBatchInfo transcodeVideoBatchInfo in listTranscodeVideoBatch)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                string strTranscodeFilePath = StaticFunctions.GetTranscodeFilePath(transcodeVideoBatchInfo.GUID,
                                                                                   siteSettings.ServiceSettings.TranscodeDirectory, videoSize);

                StaticFunctions.GetTranscodeVideoSize(videoSize, transcodeVideoBatchInfo.VideoWidth, transcodeVideoBatchInfo.VideoHeight,
                                                      out VideoSize targetVideoSize, out int targetVideoWidth, out int targetVideoHeight);

                var conversionOptions = StaticFunctions.GetConversionOptions(targetVideoSize, transcodeVideoBatchInfo.VideoWidth,
                                                                             transcodeVideoBatchInfo.VideoHeight);

                progressTaskFactory.WriteLog(string.Format("Transcoding file {0} of {1} with guid {2} and path \"{3}\" from resolution {4}x{5} to {6}x{7} ",
                                                           intCounter, intTotalCount, transcodeVideoBatchInfo.GUID, transcodeVideoBatchInfo.VideoFileInfo.FullName, transcodeVideoBatchInfo.VideoWidth,
                                                           transcodeVideoBatchInfo.VideoHeight, targetVideoWidth, targetVideoHeight),
                                             IsWindows, LogEventLevel.Information);

                ProgressTask progressTask = progressTaskFactory.GetIdleProgressTask();

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                if (progressTask == null)
                {
                    progressTask = progressTaskFactory
                                   .WaitForAnyTask()
                                   .Result;
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                string progressBarText = string.Format("{0} ({1} of {2})", transcodeVideoBatchInfo.TranscodeFileInfo.Name, intCounter, intTotalCount);

                progressTask.Task = new Task(() => {
                    TranscodeVideoProgressTask(transcodeVideoBatchInfo, videoSize, cancellationToken, progressTask, progressBarText);
                });

                progressTask.Task.Start();

                // If we are on the last item we have to wait for all tasks to complete
                if (transcodeVideoBatchInfo == lastTranscodeVideoBatch)
                {
                    progressTaskFactory.WaitForAllTasks();
                }

                intCounter++;
            }

            Log.CloseAndFlush();
        }
示例#2
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostEnvironment env, ILogger <Startup> logger)
        {
            IDBrowserConfiguration configuration = new IDBrowserConfiguration();

            Configuration.Bind(configuration);

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseSerilogRequestLogging();

            try
            {
                if (configuration.Sites != null)
                {
                    foreach (KeyValuePair <string, SiteSettings> siteKeyValuePair in configuration.Sites)
                    {
                        string                   strSiteName              = siteKeyValuePair.Key;
                        SiteSettings             siteSettings             = siteKeyValuePair.Value;
                        ConnectionStringSettings connectionStringSettings = siteSettings.ConnectionStrings;
                        ServiceSettings          serviceSettings          = siteSettings.ServiceSettings;

                        //https://www.strathweb.com/2017/04/running-multiple-independent-asp-net-core-pipelines-side-by-side-in-the-same-application/
                        app.UseBranchWithServices("/" + strSiteName,
                                                  services =>
                        {
                            services
                            .AddMvc(option => option.EnableEndpointRouting = false)
                            .AddXmlSerializerFormatters();

                            services.AddSingleton <ServiceSettings>(serviceSettings);

                            if (configuration.UseSwagger)
                            {
                                //Register the Swagger generator, defining 1 or more Swagger documents
                                services.AddSwaggerGen(c =>
                                {
                                    c.SwaggerDoc("v1", new OpenApiInfo
                                    {
                                        Title       = $"IDBrowserService Core Site \"{strSiteName}\"",
                                        Version     = "v1",
                                        Description = "Webservice for IDBrowser Android app."
                                    });

                                    // Set the comments path for the Swagger JSON and UI.
                                    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                                    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);

                                    if (File.Exists(xmlPath))
                                    {
                                        c.IncludeXmlComments(xmlPath);
                                    }
                                });
                            }

                            if (configuration.UseResponseCompression)
                            {
                                services.AddResponseCompression(options =>
                                {
                                    options.Providers.Add <BrotliCompressionProvider>();
                                    options.Providers.Add <GzipCompressionProvider>();
                                    options.EnableForHttps = true;
                                });
                            }

                            services.AddDbContextPool <IDImagerDB>(options => StaticFunctions
                                                                   .SetDbContextOptions(options, connectionStringSettings.DBType, connectionStringSettings.IDImager));
                            services.AddDbContextPool <IDImagerThumbsDB>(options => StaticFunctions
                                                                         .SetDbContextOptions(options, connectionStringSettings.DBType, connectionStringSettings.IDImagerThumbs));
                        },
                                                  appBuilder =>
                        {
                            if (configuration.UseResponseCompression)
                            {
                                appBuilder.UseResponseCompression();
                            }

                            appBuilder.UseMvc();

                            if (configuration.UseSwagger)
                            {
                                // Enable middleware to serve generated Swagger as a JSON endpoint.
                                appBuilder.UseSwagger();

                                // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
                                // specifying the Swagger JSON endpoint.
                                appBuilder.UseSwaggerUI(c =>
                                {
                                    c.SwaggerEndpoint($"/{strSiteName}/swagger/v1/swagger.json", "IDBrowserServiceCore V1");
                                });
                            }
                        });
                    }
                }

                app.Run(async c =>
                {
                    await c.Response.WriteAsync("Service online!");
                });
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
        }
        /// <summary>
        /// Generates thumbnails based on parameters
        /// </summary>
        /// <param name="configuration">Json configuration of IDBrowserService as IDBrowserConfiguration class</param>
        /// <param name="siteName">Site name to generate thumbnails</param>
        /// <param name="fromDateTime">From date filter</param>
        /// <param name="toDateTime">To date filter</param>
        /// <param name="fileFilter">File type filter</param>
        /// <param name="imageGuid">Generate single image guid</param>
        /// <param name="overwrite">Overwrite existing thumbnails</param>
        public async static void GenerateThumbnails(IDBrowserConfiguration configuration, string siteName, DateTime fromDateTime,
                                                    DateTime toDateTime, string fileFilter, string imageGuid, bool overwrite)
        {
            SiteSettings siteSettings = configuration.Sites[siteName];

            var optionsBuilder = new DbContextOptionsBuilder <IDImagerDB>();

            if (siteSettings.ConnectionStrings.DBType.Equals("MsSql"))
            {
                optionsBuilder.UseSqlServer(siteSettings.ConnectionStrings.IDImager);
            }
            else if (siteSettings.ConnectionStrings.DBType.Equals("Postgres"))
            {
                optionsBuilder.UseNpgsql(siteSettings.ConnectionStrings.IDImager);
                optionsBuilder.ReplaceService <ISqlGenerationHelper, PostgresSqlGenerationHelper>();
            }

            IDImagerDB db = new IDImagerDB(GetIDImagerDBOptionsBuilder <IDImagerDB>(siteSettings.ConnectionStrings.DBType,
                                                                                    siteSettings.ConnectionStrings.IDImager).Options);
            IDImagerThumbsDB dbThumbs = new IDImagerThumbsDB(GetIDImagerDBOptionsBuilder <IDImagerThumbsDB>(siteSettings.ConnectionStrings.DBType,
                                                                                                            siteSettings.ConnectionStrings.IDImagerThumbs).Options);

            var queryCatalogItem = from catalogItem in db.idCatalogItem.Include("idFilePath")
                                   where configuration.ImageFileExtensions.Contains(catalogItem.idFileType) ||
                                   configuration.VideoFileExtensions.Contains(catalogItem.idFileType)
                                   select catalogItem;

            if (fromDateTime != DateTime.MinValue)
            {
                queryCatalogItem = queryCatalogItem.Where(x => x.idCreated >= fromDateTime);
            }

            if (toDateTime != DateTime.MinValue)
            {
                queryCatalogItem = queryCatalogItem.Where(x => x.idCreated <= toDateTime);
            }

            if (!string.IsNullOrEmpty(fileFilter))
            {
                queryCatalogItem = queryCatalogItem.Where(x => x.idFileType.ToLower().Equals(fileFilter.ToLower()));
            }

            if (!string.IsNullOrEmpty(imageGuid))
            {
                queryCatalogItem = queryCatalogItem.Where(x => x.GUID.Equals(imageGuid, StringComparison.OrdinalIgnoreCase));
            }

            int intCountCatalogItem    = queryCatalogItem.Count();
            int intCatalogItemCounter  = 0;
            int intThumbnailsGenerated = 0;

            foreach (idCatalogItem catalogItem in queryCatalogItem)
            {
                List <String>   typesToGenerate = new List <String>();
                List <idThumbs> idThumbsT       = dbThumbs.idThumbs.Where(x => x.ImageGUID == catalogItem.GUID && x.idType.Equals("T")).ToList();
                List <idThumbs> idThumbsM       = dbThumbs.idThumbs.Where(x => x.ImageGUID == catalogItem.GUID && x.idType.Equals("M")).ToList();
                List <idThumbs> idThumbsR       = dbThumbs.idThumbs.Where(x => x.ImageGUID == catalogItem.GUID && x.idType.Equals("R")).ToList();

                if (idThumbsT.Count() == 0)
                {
                    typesToGenerate.Add("T");
                }

                if (idThumbsM.Count() == 0)
                {
                    typesToGenerate.Add("M");
                }

                if (catalogItem.idHasRecipe > 0 && idThumbsR.Count() == 0)
                {
                    typesToGenerate.Add("R");
                }

                if (overwrite)
                {
                    foreach (idThumbs thumb in idThumbsT)
                    {
                        dbThumbs.idThumbs.Remove(thumb);
                    }

                    foreach (idThumbs thumb in idThumbsM)
                    {
                        dbThumbs.idThumbs.Remove(thumb);
                    }

                    foreach (idThumbs thumb in idThumbsR)
                    {
                        dbThumbs.idThumbs.Remove(thumb);
                    }

                    typesToGenerate.Clear();
                    typesToGenerate.Add("T");
                    typesToGenerate.Add("M");
                    if (catalogItem.idHasRecipe > 0)
                    {
                        typesToGenerate.Add("R");
                    }
                }

                if (typesToGenerate.Count() > 0)
                {
                    try
                    {
                        SaveImageThumbnailResult result = await StaticFunctions.SaveImageThumbnail(catalogItem, db, dbThumbs, typesToGenerate,
                                                                                                   siteSettings.ServiceSettings);

                        foreach (Exception ex in result.Exceptions)
                        {
                            LogGenerateThumbnailsException(ex);
                            Console.WriteLine(ex.ToString());
                        }

                        if (result.Exceptions.Count > 0)
                        {
                            LogGenerateThumbnailsFailedCatalogItem(catalogItem);
                        }

                        intThumbnailsGenerated += result.ImageStreams.Count();
                    }
                    catch (Exception e)
                    {
                        LogGenerateThumbnailsException(e);
                        LogGenerateThumbnailsFailedCatalogItem(catalogItem);
                        Console.WriteLine(e.ToString());
                    }
                }

                intCatalogItemCounter += 1;

                Console.CursorLeft = 0;
                Console.Write(String.Format("{0} of {1} catalogitems checked. {2} thumbnails generated", intCatalogItemCounter, intCountCatalogItem, intThumbnailsGenerated));
            }
        }
        public static void Handle(string[] args)
        {
            IDBrowserConfiguration configuration = new IDBrowserConfiguration();

            Configuration.Bind(configuration);

            if (args[0] == nameof(ConsoleFunctions.TranscodeAllVideos))
            {
                if (args.Count() < 3)
                {
                    Console.WriteLine("Please specify the site name, video size (e.g. Hd480, Hd720, Hd1080), number of FFmpeg instances (optional, default 2, max 12) and log level (optional, default Error, possible values Verbose, Debug, Information, Warning, Error and Fatal) to transcode videos.");
                }
                else
                {
                    string strSiteName  = args[1];
                    string strVideoSize = args[2];
                    int    taskCount    = 2;
                    Serilog.Events.LogEventLevel logLevel = LogEventLevel.Error;

                    if (args.Count() > 3)
                    {
                        taskCount = Math.Min(12, Math.Max(1, int.Parse(args[3])));
                    }

                    if (args.Count() > 4)
                    {
                        logLevel = (LogEventLevel)Enum.Parse(typeof(LogEventLevel), args[4], true);
                    }

                    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

                    Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) =>
                    {
                        cancellationTokenSource.Cancel();
                        e.Cancel = true;
                    };

                    ConsoleFunctions.TranscodeAllVideos(configuration, cancellationTokenSource.Token, strSiteName,
                                                        strVideoSize, logLevel, taskCount);
                    Console.WriteLine("Transcoding complete");
                }
            }
            else if (args[0] == nameof(ConsoleFunctions.GenerateThumbnails))
            {
                if (args.Count() < 2)
                {
                    Console.WriteLine("Please specify the site name");
                }
                else
                {
                    string strSiteName = args[1];

                    Console.WriteLine("Please enter optional from datetime: ");
                    DateTime.TryParse(Console.ReadLine(), out DateTime fromDateTime);

                    Console.WriteLine("Please enter optional to datetime: ");
                    DateTime.TryParse(Console.ReadLine(), out DateTime toDateTime);

                    Console.WriteLine("Please enter optional file filter: ");
                    string strFileFilter = Console.ReadLine();

                    Console.WriteLine("Please enter optional image guid: ");
                    string strImageGuid = Console.ReadLine();

                    Console.WriteLine("Please enter 'true' when thumbnails should be overwritten: ");
                    bool.TryParse(Console.ReadLine(), out bool overwrite);

                    Console.WriteLine("Generating thumbnails...");
                    ConsoleFunctions.GenerateThumbnails(configuration, strSiteName, fromDateTime,
                                                        toDateTime, strFileFilter, strImageGuid, overwrite);
                }
            }
            else
            {
                Console.WriteLine("Command not recognized. Possible Commands:");
                Console.WriteLine("TranscodeAllVideos");
            }
        }