diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a97b3a2a8..d4c63e8a3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.7 + rev: v0.14.2 hooks: - id: ruff args: @@ -26,7 +26,7 @@ repos: hooks: - id: gitleaks - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: end-of-file-fixer files: ^.*(\.js|\.java|\.py|\.yml)$ diff --git a/Dockerfile b/Dockerfile index 597590162..d36ea60a9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -55,6 +55,7 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a openssl \ openssl-dev \ openjdk21-jre \ + ffmpeg \ # Doc conversion gcompat \ libc6-compat \ diff --git a/Dockerfile.dev b/Dockerfile.dev index eba01cf02..517e94b95 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -19,6 +19,7 @@ RUN apt-get update && apt-get install -y \ # settings.yml | tessdataDir: /usr/share/tesseract-ocr/5/tessdata tesseract-ocr \ tesseract-ocr-eng \ + ffmpeg \ fonts-terminus fonts-dejavu fonts-font-awesome fonts-noto fonts-noto-core fonts-noto-cjk fonts-noto-extra fonts-liberation fonts-linuxlibertine fonts-urw-base35 \ python3-uno \ python3-venv \ diff --git a/Dockerfile.fat b/Dockerfile.fat index a2de38b45..b6afec888 100644 --- a/Dockerfile.fat +++ b/Dockerfile.fat @@ -69,6 +69,7 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a openssl \ openssl-dev \ openjdk21-jre \ + ffmpeg \ # Doc conversion gcompat \ libc6-compat \ diff --git a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java index ca9e7ff57..1f734f5a6 100644 --- a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java +++ b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java @@ -647,6 +647,7 @@ public class ApplicationProperties { private int tesseractSessionLimit; private int ghostscriptSessionLimit; private int ocrMyPdfSessionLimit; + private int ffmpegSessionLimit; public int getQpdfSessionLimit() { return qpdfSessionLimit > 0 ? qpdfSessionLimit : 2; @@ -687,6 +688,10 @@ public class ApplicationProperties { public int getOcrMyPdfSessionLimit() { return ocrMyPdfSessionLimit > 0 ? ocrMyPdfSessionLimit : 2; } + + public int getFfmpegSessionLimit() { + return ffmpegSessionLimit > 0 ? ffmpegSessionLimit : 2; + } } @Data @@ -713,6 +718,7 @@ public class ApplicationProperties { private long qpdfTimeoutMinutes; private long ghostscriptTimeoutMinutes; private long ocrMyPdfTimeoutMinutes; + private long ffmpegTimeoutMinutes; public long getTesseractTimeoutMinutes() { return tesseractTimeoutMinutes > 0 ? tesseractTimeoutMinutes : 30; @@ -753,6 +759,10 @@ public class ApplicationProperties { public long getOcrMyPdfTimeoutMinutes() { return ocrMyPdfTimeoutMinutes > 0 ? ocrMyPdfTimeoutMinutes : 30; } + + public long getFfmpegTimeoutMinutes() { + return ffmpegTimeoutMinutes > 0 ? ffmpegTimeoutMinutes : 30; + } } } } diff --git a/app/common/src/main/java/stirling/software/common/util/CheckProgramInstall.java b/app/common/src/main/java/stirling/software/common/util/CheckProgramInstall.java index f39daf8ae..0927f8c59 100644 --- a/app/common/src/main/java/stirling/software/common/util/CheckProgramInstall.java +++ b/app/common/src/main/java/stirling/software/common/util/CheckProgramInstall.java @@ -11,6 +11,8 @@ public class CheckProgramInstall { private static final List PYTHON_COMMANDS = Arrays.asList("python3", "python"); private static boolean pythonAvailableChecked = false; private static String availablePythonCommand = null; + private static boolean ffmpegAvailableChecked = false; + private static boolean ffmpegAvailable = false; /** * Checks which Python command is available and returns it. @@ -56,4 +58,25 @@ public class CheckProgramInstall { public static boolean isPythonAvailable() { return getAvailablePythonCommand() != null; } + + /** + * Checks if FFmpeg is available on the system. + * + * @return true if FFmpeg is installed and accessible, false otherwise. + */ + public static boolean isFfmpegAvailable() { + if (!ffmpegAvailableChecked) { + try { + ProcessExecutorResult result = + ProcessExecutor.getInstance(ProcessExecutor.Processes.FFMPEG) + .runCommandWithOutputHandling(Arrays.asList("ffmpeg", "-version")); + ffmpegAvailable = true; + } catch (IOException | InterruptedException e) { + ffmpegAvailable = false; + } finally { + ffmpegAvailableChecked = true; + } + } + return ffmpegAvailable; + } } diff --git a/app/common/src/main/java/stirling/software/common/util/ExceptionUtils.java b/app/common/src/main/java/stirling/software/common/util/ExceptionUtils.java index b5e200aff..1979621a7 100644 --- a/app/common/src/main/java/stirling/software/common/util/ExceptionUtils.java +++ b/app/common/src/main/java/stirling/software/common/util/ExceptionUtils.java @@ -34,11 +34,14 @@ public class ExceptionUtils { if (context != null && !context.isEmpty()) { message = String.format( - "Error %s: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation.", + "Error %s: PDF file appears to be corrupted or damaged. Please try" + + " using the 'Repair PDF' feature first to fix the file before" + + " proceeding with this operation.", context); } else { message = - "PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation."; + "PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF'" + + " feature first to fix the file before proceeding with this operation."; } return new IOException(message, cause); } @@ -51,7 +54,8 @@ public class ExceptionUtils { */ public static IOException createMultiplePdfCorruptedException(Exception cause) { String message = - "One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them."; + "One or more PDF files appear to be corrupted or damaged. Please try using the" + + " 'Repair PDF' feature on each file first before attempting to merge them."; return new IOException(message, cause); } @@ -63,7 +67,10 @@ public class ExceptionUtils { */ public static IOException createPdfEncryptionException(Exception cause) { String message = - "The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy."; + "The PDF appears to have corrupted encryption data. This can happen when the PDF" + + " was created with incompatible encryption methods. Please try using the" + + " 'Repair PDF' feature first, or contact the document creator for a new" + + " copy."; return new IOException(message, cause); } @@ -75,7 +82,8 @@ public class ExceptionUtils { */ public static IOException createPdfPasswordException(Exception cause) { String message = - "The PDF Document is passworded and either the password was not provided or was incorrect"; + "The PDF Document is passworded and either the password was not provided or was" + + " incorrect"; return new IOException(message, cause); } @@ -180,6 +188,15 @@ public class ExceptionUtils { "error.toolRequired", "{0} is required for {1}", null, "Python", "WebP conversion"); } + public static IOException createFfmpegRequiredException() { + return createIOException( + "error.toolRequired", + "{0} is required for {1}", + null, + "FFmpeg", + "PDF to Video Slideshow conversion"); + } + /** Create file operation exceptions. */ public static IOException createFileNotFoundException(String fileId) { return createIOException("error.fileNotFound", "File not found with ID: {0}", null, fileId); @@ -345,9 +362,11 @@ public class ExceptionUtils { int pageNumber, int dpi, Throwable cause) { String message = MessageFormat.format( - "Out of memory or image-too-large error while rendering PDF page {0} at {1} DPI. " - + "This can occur when the resulting image exceeds Java's array/memory limits (e.g., NegativeArraySizeException). " - + "Please use a lower DPI value (recommended: 150 or less) or process the document in smaller chunks.", + "Out of memory or image-too-large error while rendering PDF page {0} at {1}" + + " DPI. This can occur when the resulting image exceeds Java's" + + " array/memory limits (e.g., NegativeArraySizeException). Please use" + + " a lower DPI value (recommended: 150 or less) or process the" + + " document in smaller chunks.", pageNumber, dpi); return new RuntimeException(message, cause); } @@ -378,9 +397,11 @@ public class ExceptionUtils { public static RuntimeException createOutOfMemoryDpiException(int dpi, Throwable cause) { String message = MessageFormat.format( - "Out of memory or image-too-large error while rendering PDF at {0} DPI. " - + "This can occur when the resulting image exceeds Java's array/memory limits (e.g., NegativeArraySizeException). " - + "Please use a lower DPI value (recommended: 150 or less) or process the document in smaller chunks.", + "Out of memory or image-too-large error while rendering PDF at {0} DPI." + + " This can occur when the resulting image exceeds Java's array/memory" + + " limits (e.g., NegativeArraySizeException). Please use a lower DPI" + + " value (recommended: 150 or less) or process the document in smaller" + + " chunks.", dpi); return new RuntimeException(message, cause); } diff --git a/app/common/src/main/java/stirling/software/common/util/ProcessExecutor.java b/app/common/src/main/java/stirling/software/common/util/ProcessExecutor.java index 514e16212..9b260d9cf 100644 --- a/app/common/src/main/java/stirling/software/common/util/ProcessExecutor.java +++ b/app/common/src/main/java/stirling/software/common/util/ProcessExecutor.java @@ -71,6 +71,11 @@ public class ProcessExecutor { .getProcessExecutor() .getSessionLimit() .getInstallAppSessionLimit(); + case FFMPEG -> + applicationProperties + .getProcessExecutor() + .getSessionLimit() + .getFfmpegSessionLimit(); case TESSERACT -> applicationProperties .getProcessExecutor() @@ -125,6 +130,11 @@ public class ProcessExecutor { .getProcessExecutor() .getTimeoutMinutes() .getInstallAppTimeoutMinutes(); + case FFMPEG -> + applicationProperties + .getProcessExecutor() + .getTimeoutMinutes() + .getFfmpegTimeoutMinutes(); case TESSERACT -> applicationProperties .getProcessExecutor() @@ -302,7 +312,8 @@ public class ProcessExecutor { TESSERACT, QPDF, GHOSTSCRIPT, - OCR_MY_PDF + OCR_MY_PDF, + FFMPEG } @Setter diff --git a/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java b/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java index e5c89fc26..af325d249 100644 --- a/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java +++ b/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java @@ -2,6 +2,7 @@ package stirling.software.common.model; import static org.junit.jupiter.api.Assertions.*; +import java.io.File; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; @@ -45,11 +46,15 @@ class ApplicationPropertiesLogicTest { String expectedLibre = Paths.get(expectedBase, "libreoffice").toString(); assertEquals(expectedLibre, tfm.getLibreofficeDir()); - tfm.setBaseTmpDir("/custom/base"); - assertEquals("/custom/base", normalize.apply(tfm.getBaseTmpDir())); + tfm.setBaseTmpDir(File.separator + "custom" + File.separator + "base"); + assertEquals( + File.separator + "custom" + File.separator + "base", + normalize.apply(tfm.getBaseTmpDir())); - tfm.setLibreofficeDir("/opt/libre"); - assertEquals("/opt/libre", normalize.apply(tfm.getLibreofficeDir())); + tfm.setLibreofficeDir(File.separator + "opt" + File.separator + "libre"); + assertEquals( + File.separator + "opt" + File.separator + "libre", + normalize.apply(tfm.getLibreofficeDir())); } @Test @@ -240,12 +245,13 @@ class ApplicationPropertiesLogicTest { void collection_isValid_true_when_non_empty_even_if_element_is_blank() { ApplicationProperties.Security.OAUTH2 oauth2 = new ApplicationProperties.Security.OAUTH2(); - // Aktuelles Verhalten: prüft NUR !isEmpty(), nicht Inhalt + // Current behavior: checks ONLY !isEmpty(), not the content Collection oneBlank = new ArrayList<>(); oneBlank.add(" "); assertTrue( oauth2.isValid(oneBlank, "scopes"), - "Dokumentiert aktuelles Verhalten: nicht-leere Liste gilt als gültig, auch wenn Element leer/blank ist"); + "Documents current behavior: non-empty list is considered valid, even if an element" + + " is empty/blank"); } } diff --git a/app/common/src/test/java/stirling/software/common/util/CheckProgramInstallTest.java b/app/common/src/test/java/stirling/software/common/util/CheckProgramInstallTest.java index a994937af..170290292 100644 --- a/app/common/src/test/java/stirling/software/common/util/CheckProgramInstallTest.java +++ b/app/common/src/test/java/stirling/software/common/util/CheckProgramInstallTest.java @@ -26,6 +26,7 @@ class CheckProgramInstallTest { private MockedStatic mockProcessExecutor; private ProcessExecutor mockExecutor; + private ProcessExecutor mockFfmpegExecutor; @BeforeEach void setUp() throws Exception { @@ -34,10 +35,14 @@ class CheckProgramInstallTest { // Set up mock for ProcessExecutor mockExecutor = Mockito.mock(ProcessExecutor.class); + mockFfmpegExecutor = Mockito.mock(ProcessExecutor.class); mockProcessExecutor = mockStatic(ProcessExecutor.class); mockProcessExecutor .when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)) .thenReturn(mockExecutor); + mockProcessExecutor + .when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.FFMPEG)) + .thenReturn(mockFfmpegExecutor); } @AfterEach @@ -59,6 +64,15 @@ class CheckProgramInstallTest { CheckProgramInstall.class.getDeclaredField("availablePythonCommand"); availablePythonCommandField.setAccessible(true); availablePythonCommandField.set(null, null); + + Field ffmpegAvailableCheckedField = + CheckProgramInstall.class.getDeclaredField("ffmpegAvailableChecked"); + ffmpegAvailableCheckedField.setAccessible(true); + ffmpegAvailableCheckedField.set(null, false); + + Field ffmpegAvailableField = CheckProgramInstall.class.getDeclaredField("ffmpegAvailable"); + ffmpegAvailableField.setAccessible(true); + ffmpegAvailableField.set(null, false); } @Test @@ -204,4 +218,45 @@ class CheckProgramInstallTest { // Verify getAvailablePythonCommand was called internally verify(mockExecutor).runCommandWithOutputHandling(Arrays.asList("python3", "--version")); } + + @Test + void testIsFfmpegAvailable_WhenInstalled() throws Exception { + resetStaticFields(); + ProcessExecutorResult result = Mockito.mock(ProcessExecutorResult.class); + when(mockFfmpegExecutor.runCommandWithOutputHandling(Arrays.asList("ffmpeg", "-version"))) + .thenReturn(result); + + assertTrue(CheckProgramInstall.isFfmpegAvailable()); + verify(mockFfmpegExecutor) + .runCommandWithOutputHandling(Arrays.asList("ffmpeg", "-version")); + } + + @Test + void testIsFfmpegAvailable_WhenNotInstalled() throws Exception { + resetStaticFields(); + when(mockFfmpegExecutor.runCommandWithOutputHandling(Arrays.asList("ffmpeg", "-version"))) + .thenThrow(new IOException("Command not found")); + + assertFalse(CheckProgramInstall.isFfmpegAvailable()); + verify(mockFfmpegExecutor) + .runCommandWithOutputHandling(Arrays.asList("ffmpeg", "-version")); + } + + @Test + void testIsFfmpegAvailable_CachesResult() throws Exception { + resetStaticFields(); + ProcessExecutorResult result = Mockito.mock(ProcessExecutorResult.class); + when(mockFfmpegExecutor.runCommandWithOutputHandling(Arrays.asList("ffmpeg", "-version"))) + .thenReturn(result); + + assertTrue(CheckProgramInstall.isFfmpegAvailable()); + + when(mockFfmpegExecutor.runCommandWithOutputHandling(Arrays.asList("ffmpeg", "-version"))) + .thenThrow(new IOException("Command not found")); + + assertTrue(CheckProgramInstall.isFfmpegAvailable()); + + verify(mockFfmpegExecutor, times(1)) + .runCommandWithOutputHandling(Arrays.asList("ffmpeg", "-version")); + } } diff --git a/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java b/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java index f07f05537..65bcd420d 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java @@ -262,6 +262,7 @@ public class EndpointConfiguration { addEndpointToGroup("Convert", "eml-to-pdf"); addEndpointToGroup("Convert", "pdf-to-vector"); addEndpointToGroup("Convert", "vector-to-pdf"); + addEndpointToGroup("Convert", "pdf-to-video"); // Adding endpoints to "Security" group addEndpointToGroup("Security", "add-password"); @@ -391,6 +392,7 @@ public class EndpointConfiguration { addEndpointToGroup("Java", "add-attachments"); addEndpointToGroup("Java", "compress-pdf"); addEndpointToGroup("rar", "pdf-to-cbr"); + addEndpointToGroup("Java", "pdf-to-video"); // Javascript addEndpointToGroup("Javascript", "pdf-organizer"); @@ -447,6 +449,9 @@ public class EndpointConfiguration { // Pdftohtml dependent endpoints addEndpointToGroup("Pdftohtml", "pdf-to-html"); addEndpointToGroup("Pdftohtml", "pdf-to-markdown"); + + // FFmpeg dependent endpoints + addEndpointToGroup("FFmpeg", "pdf-to-video"); } private void processEnvironmentConfigs() { @@ -493,7 +498,8 @@ public class EndpointConfiguration { || "Javascript".equals(group) || "Weasyprint".equals(group) || "Pdftohtml".equals(group) - || "rar".equals(group); + || "rar".equals(group) + || "FFmpeg".equals(group); } private boolean isEndpointEnabledDirectly(String endpoint) { diff --git a/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java index 237bdb412..9f8d7d17c 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java @@ -67,6 +67,7 @@ public class ExternalAppDepConfig { tmp.put("qpdf", List.of("qpdf")); tmp.put("tesseract", List.of("tesseract")); tmp.put("rar", List.of("rar")); + tmp.put("ffmpeg", List.of("FFmpeg")); this.commandToGroupMapping = Collections.unmodifiableMap(tmp); } diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPdfToVideoController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPdfToVideoController.java new file mode 100644 index 000000000..0edf95739 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPdfToVideoController.java @@ -0,0 +1,281 @@ +package stirling.software.SPDF.controller.api.converters; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import javax.imageio.ImageIO; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.rendering.ImageType; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import io.github.pixee.security.Filenames; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +import lombok.RequiredArgsConstructor; + +import stirling.software.SPDF.model.api.converters.PdfToVideoRequest; +import stirling.software.common.model.ApplicationProperties; +import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ApplicationContextProvider; +import stirling.software.common.util.CheckProgramInstall; +import stirling.software.common.util.ExceptionUtils; +import stirling.software.common.util.ProcessExecutor; +import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; +import stirling.software.common.util.TempDirectory; +import stirling.software.common.util.TempFile; +import stirling.software.common.util.TempFileManager; +import stirling.software.common.util.WebResponseUtils; + +@RestController +@RequestMapping("/api/v1/convert") +@Tag(name = "Convert", description = "Convert APIs") +@RequiredArgsConstructor +public class ConvertPdfToVideoController { + + private static final Set SUPPORTED_FORMATS = Set.of("mp4", "webm"); + private static final Map RESOLUTION_FILTERS = + Map.of( + "ORIGINAL", "scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=1", + "1080P", "scale=-2:1080,setsar=1", + "720P", "scale=-2:720,setsar=1", + "480P", "scale=-2:480,setsar=1"); + + private final CustomPDFDocumentFactory pdfDocumentFactory; + private final TempFileManager tempFileManager; + + @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/video") + @Operation( + summary = "Convert PDF to Video Slideshow", + description = + "This endpoint converts a PDF document into a slideshow-style video." + + " Input:PDF Output:Video Type:SISO") + public ResponseEntity convertPdfToVideo(@ModelAttribute PdfToVideoRequest request) + throws Exception { + if (!CheckProgramInstall.isFfmpegAvailable()) { + throw ExceptionUtils.createFfmpegRequiredException(); + } + + MultipartFile inputFile = request.getFileInput(); + if (inputFile == null || inputFile.isEmpty()) { + throw ExceptionUtils.createPdfFileRequiredException(); + } + if (!MediaType.APPLICATION_PDF_VALUE.equals(inputFile.getContentType())) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + float opacity = request.getOpacity() != null ? request.getOpacity() : 1.0f; + if (opacity < 0.0f || opacity > 1.0f) { + throw ExceptionUtils.createIllegalArgumentException( + "error.invalidFormat", "Invalid {0} format: {1}", "opacity", opacity); + } + + String format = normalizeFormat(request.getVideoFormat()); + int secondsPerPage = request.getSecondsPerPage() != null ? request.getSecondsPerPage() : 3; + if (secondsPerPage <= 0) { + throw ExceptionUtils.createIllegalArgumentException( + "error.invalidFormat", + "Invalid {0} format: {1}", + "secondsPerPage", + secondsPerPage); + } + int dpi = request.getDpi() != null ? request.getDpi() : 150; + int maxDpi = getMaxDpi(); + if (dpi > maxDpi) { + throw ExceptionUtils.createIllegalArgumentException( + "error.dpiExceedsLimit", + "DPI value {0} exceeds maximum safe limit of {1}.", + dpi, + maxDpi); + } + if (dpi < 72) { + throw ExceptionUtils.createIllegalArgumentException( + "error.invalidFormat", "Invalid {0} format: {1}", "dpi", dpi); + } + + String resolution = + request.getResolution() != null + ? request.getResolution().toUpperCase(Locale.ROOT) + : "ORIGINAL"; + if (!RESOLUTION_FILTERS.containsKey(resolution)) { + resolution = "ORIGINAL"; + } + + String watermarkText = request.getWatermarkText(); + boolean isWatermarkEnabled = watermarkText != null && !watermarkText.isBlank(); + + String originalPdfFileName = Filenames.toSimpleFileName(inputFile.getOriginalFilename()); + if (originalPdfFileName == null || originalPdfFileName.isBlank()) { + originalPdfFileName = "document.pdf"; + } + String pdfBaseName = + originalPdfFileName.contains(".") + ? originalPdfFileName.substring(0, originalPdfFileName.lastIndexOf('.')) + : originalPdfFileName; + + try (TempFile inputTempFile = new TempFile(tempFileManager, ".pdf"); + TempDirectory framesDirectory = new TempDirectory(tempFileManager); + TempFile outputVideo = new TempFile(tempFileManager, "." + format)) { + + inputFile.transferTo(inputTempFile.getFile()); + + generateFrames( + inputTempFile.getPath(), + framesDirectory.getPath(), + dpi, + opacity, + watermarkText, + isWatermarkEnabled); + + DecimalFormat decimalFormat = + new DecimalFormat("0.######", DecimalFormatSymbols.getInstance(Locale.ROOT)); + String frameRate = decimalFormat.format(1.0d / secondsPerPage); + List command = buildFfmpegCommand(format, resolution, frameRate, outputVideo); + + ProcessExecutorResult result = + ProcessExecutor.getInstance(ProcessExecutor.Processes.FFMPEG) + .runCommandWithOutputHandling( + command, framesDirectory.getPath().toFile()); + + byte[] videoBytes = Files.readAllBytes(outputVideo.getPath()); + MediaType mediaType = getMediaType(format); + String outputName = pdfBaseName + "-video." + format; + return WebResponseUtils.bytesToWebResponse(videoBytes, outputName, mediaType); + } + } + + private void generateFrames( + Path inputPdf, + Path outputDir, + int dpi, + float opacity, + String watermarkText, + boolean isWatermarkEnabled) + throws IOException { + try (PDDocument document = pdfDocumentFactory.load(inputPdf.toFile())) { + PDFRenderer renderer = new PDFRenderer(document); + renderer.setSubsamplingAllowed(true); + int pageCount = document.getNumberOfPages(); + if (pageCount == 0) { + throw ExceptionUtils.createIllegalArgumentException( + "error.invalidFormat", "Invalid {0} format: {1}", "PDF", "no pages"); + } + for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) { + BufferedImage image = renderer.renderImageWithDPI(pageIndex, dpi, ImageType.RGB); + if (isWatermarkEnabled) { + applyWatermark(image, opacity, watermarkText); + } + Path framePath = + outputDir.resolve( + String.format(Locale.ROOT, "frame_%05d.png", pageIndex + 1)); + ImageIO.write(image, "png", framePath.toFile()); + } + } + } + + private void applyWatermark(BufferedImage image, float opacity, String watermarkText) { + Graphics2D graphics = image.createGraphics(); + try { + graphics.setRenderingHint( + java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, + java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + int baseDimension = Math.min(image.getWidth(), image.getHeight()); + int fontSize = Math.max(32, baseDimension / 5); + Font font = new Font(Font.SANS_SERIF, Font.BOLD, fontSize); + graphics.setFont(font); + + FontMetrics metrics = graphics.getFontMetrics(font); + int textWidth = metrics.stringWidth(watermarkText); + int textHeight = metrics.getAscent(); + + AffineTransform originalTransform = graphics.getTransform(); + double angle = Math.atan2(image.getHeight(), image.getWidth()); + graphics.translate(image.getWidth() / 2.0, image.getHeight() / 2.0); + graphics.rotate(-angle); + + // Draw shadow + graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity / 2)); + graphics.setColor(Color.BLACK); + graphics.drawString(watermarkText, -textWidth / 2f + 3, textHeight / 2f + 3); + + // Draw main text + graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity)); + graphics.setColor(Color.WHITE); + graphics.drawString(watermarkText, -textWidth / 2f, textHeight / 2f); + + graphics.setTransform(originalTransform); + } finally { + graphics.dispose(); + } + } + + private List buildFfmpegCommand( + String format, String resolution, String frameRate, TempFile outputVideo) { + List command = new ArrayList<>(); + command.add("ffmpeg"); + command.add("-y"); + command.add("-framerate"); + command.add(frameRate); + command.add("-i"); + command.add("frame_%05d.png"); + command.add("-vf"); + command.add( + RESOLUTION_FILTERS.getOrDefault(resolution, RESOLUTION_FILTERS.get("ORIGINAL"))); + if ("mp4".equals(format)) { + command.addAll( + List.of("-c:v", "libx264", "-pix_fmt", "yuv420p", "-movflags", "+faststart")); + } else if ("webm".equals(format)) { + command.addAll(List.of("-c:v", "libvpx-vp9", "-b:v", "0", "-crf", "30")); + } + command.add(outputVideo.getAbsolutePath()); + return command; + } + + private String normalizeFormat(String requestedFormat) { + String format = requestedFormat != null ? requestedFormat.toLowerCase(Locale.ROOT) : "mp4"; + if (!SUPPORTED_FORMATS.contains(format)) { + format = "mp4"; + } + return format; + } + + private int getMaxDpi() { + ApplicationProperties properties = + ApplicationContextProvider.getBean(ApplicationProperties.class); + if (properties != null && properties.getSystem() != null) { + return properties.getSystem().getMaxDPI(); + } + return 500; + } + + private MediaType getMediaType(String format) { + return switch (format) { + case "webm" -> MediaType.valueOf("video/webm"); + default -> MediaType.valueOf("video/mp4"); + }; + } +} diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/web/ConverterWebController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/ConverterWebController.java index 076cc9f09..db6c62bc4 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/web/ConverterWebController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/web/ConverterWebController.java @@ -186,4 +186,18 @@ public class ConverterWebController { model.addAttribute("currentPage", "eml-to-pdf"); return "convert/eml-to-pdf"; } + + @GetMapping("/pdf-to-video") + @Hidden + public String pdfToVideo(Model model) { + ApplicationProperties properties = + ApplicationContextProvider.getBean(ApplicationProperties.class); + if (properties != null && properties.getSystem() != null) { + model.addAttribute("maxDPI", properties.getSystem().getMaxDPI()); + } else { + model.addAttribute("maxDPI", 500); + } + model.addAttribute("currentPage", "pdf-to-video"); + return "convert/pdf-to-video"; + } } diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToVideoRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToVideoRequest.java new file mode 100644 index 000000000..422664611 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToVideoRequest.java @@ -0,0 +1,53 @@ +package stirling.software.SPDF.model.api.converters; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import stirling.software.common.model.api.PDFFile; + +@Data +@EqualsAndHashCode(callSuper = true) +public class PdfToVideoRequest extends PDFFile { + + @Schema( + description = "The output video format", + allowableValues = {"mp4", "webm"}, + defaultValue = "mp4") + private String videoFormat = "mp4"; + + @Schema( + description = "Seconds each page should appear in the video", + minimum = "1", + maximum = "30", + defaultValue = "3") + private Integer secondsPerPage = 3; + + @Schema( + description = "Target video resolution", + allowableValues = {"ORIGINAL", "1080p", "720p", "480p"}, + defaultValue = "ORIGINAL") + private String resolution = "ORIGINAL"; + + @Schema( + description = "DPI to render PDF pages before encoding", + minimum = "72", + maximum = "500", + defaultValue = "150") + private Integer dpi = 150; + + @Schema( + description = + "Opacity of the watermark (only applied if a watermark text is specified)", + minimum = "0.0", + maximum = "1.0", + defaultValue = "0.1") + private Float opacity = 0.1f; + + @Schema( + description = "Watermark text to overlay on the video", + example = "Stirling Software", + defaultValue = "Stirling Software") + private String watermarkText; +} diff --git a/app/core/src/main/resources/messages_ar_AR.properties b/app/core/src/main/resources/messages_ar_AR.properties index 7a4702dde..f8f94ee5c 100644 --- a/app/core/src/main/resources/messages_ar_AR.properties +++ b/app/core/src/main/resources/messages_ar_AR.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=تحويل PDF إلى صورة home.pdfToImage.desc=تحويل ملف PDF إلى صورة. (PNG ، JPEG ، GIF) pdfToImage.tags=تحويل,صورة,jpg,صورة,صورة فوتوغرافية +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=منظم home.pdfOrganiser.desc=إزالة / إعادة ترتيب الصفحات بأي ترتيب pdfOrganiser.tags=مزدوج,زوجي,فردي,ترتيب,نقل @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(مثال: 1,2,8 أو 4,7,12-16 أو 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=إضافة كلمة مرور addPassword.header=إضافة كلمة مرور (تشفير) diff --git a/app/core/src/main/resources/messages_az_AZ.properties b/app/core/src/main/resources/messages_az_AZ.properties index 09891fc75..b433016ed 100644 --- a/app/core/src/main/resources/messages_az_AZ.properties +++ b/app/core/src/main/resources/messages_az_AZ.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF-dən Şəkilə home.pdfToImage.desc=PDF-i Şəkilə Çevir. (PNG, JPEG, GIF) pdfToImage.tags=çevirmə,şəkil,jpg,fotoşəkil,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Səhifələri Sırala home.pdfOrganiser.desc=Səhifələri Sil/Sırasını Dəyiş pdfOrganiser.tags=duplex,tək,cüt,sırala,yerini dəyiş @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(məsələn, 1,2,8 və ya 4,7,12-16 və ya 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Şifr Əlavə Et addPassword.header=Şifr Əlavə Et (Şifrləmə) diff --git a/app/core/src/main/resources/messages_bg_BG.properties b/app/core/src/main/resources/messages_bg_BG.properties index 19575e6c7..69277aea5 100644 --- a/app/core/src/main/resources/messages_bg_BG.properties +++ b/app/core/src/main/resources/messages_bg_BG.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF към изображение home.pdfToImage.desc=Преобразуване на PDF към изображение. (PNG, JPEG, GIF) pdfToImage.tags=преобразуване,img,jpg,изображение,снимка +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Организиране home.pdfOrganiser.desc=Премахване/пренареждане на страници към произволен ред pdfOrganiser.tags=дуплекс,четно,нечетно,сортиране,преместване @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Добавяне на парола addPassword.header=Добавяне на парола (Шифроване) diff --git a/app/core/src/main/resources/messages_bo_CN.properties b/app/core/src/main/resources/messages_bo_CN.properties index 02986a4c9..0d006ec9a 100644 --- a/app/core/src/main/resources/messages_bo_CN.properties +++ b/app/core/src/main/resources/messages_bo_CN.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF ནས་པར་རིས་ལ། home.pdfToImage.desc=PDF ནས་པར་རིས་ (PNG, JPEG, GIF) ལ་བསྒྱུར་བ། pdfToImage.tags=བསྒྱུར་བ།,པར་རིས།,jpg,པར།,འདྲ་པར། +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=གོ་སྒྲིག home.pdfOrganiser.desc=ཤོག་ངོས་རྣམས་གོ་རིམ་གང་རུང་དུ་སུབ་པའམ་བསྐྱར་སྒྲིག་བྱེད་པ། pdfOrganiser.tags=ཤོག་ངོས་གཉིས་མ།,ཨང་གྲངས་ཟུང་ལྡན།,ཨང་གྲངས་ཡ་གྲངས།,གོ་རིམ་སྒྲིག་པ།,སྤོ་བ། @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(དཔེར་ན། 1,2,8 ཡང་ན་ 4,7,12-16 pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=གསང་ཚིག་སྣོན་པ། addPassword.header=གསང་ཚིག་སྣོན་པ། (གསང་སྡོམ།) diff --git a/app/core/src/main/resources/messages_ca_CA.properties b/app/core/src/main/resources/messages_ca_CA.properties index 75ce99c11..3192b6b94 100644 --- a/app/core/src/main/resources/messages_ca_CA.properties +++ b/app/core/src/main/resources/messages_ca_CA.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF a Imatge home.pdfToImage.desc=Converteix PDF a imatge (PNG, JPEG, GIF) pdfToImage.tags=conversió,img,jpg,imatge,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organitza home.pdfOrganiser.desc=Elimina/reorganitza pàgines en qualsevol ordre pdfOrganiser.tags=duplex,parells,senars,ordenar,moure @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(p. ex. 1,2,8 o 4,7,12-16 o 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Afegir Contrasenya addPassword.header=Afegir contrasenya (Encriptat) diff --git a/app/core/src/main/resources/messages_cs_CZ.properties b/app/core/src/main/resources/messages_cs_CZ.properties index ab86bd9d0..d67f49966 100644 --- a/app/core/src/main/resources/messages_cs_CZ.properties +++ b/app/core/src/main/resources/messages_cs_CZ.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF na obrázek home.pdfToImage.desc=Převést PDF na obrázek. (PNG, JPEG, GIF) pdfToImage.tags=převod,img,jpg,obrázek,fotka +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Uspořádat home.pdfOrganiser.desc=Odstranit/přeuspořádat stránky v libovolném pořadí pdfOrganiser.tags=duplex,sudý,lichý,seřadit,přesunout @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(např. 1,2,8 nebo 4,7,12-16 nebo 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Přidat heslo addPassword.header=Přidat heslo (Zašifrovat) diff --git a/app/core/src/main/resources/messages_da_DK.properties b/app/core/src/main/resources/messages_da_DK.properties index 86fb91418..d2ad10725 100644 --- a/app/core/src/main/resources/messages_da_DK.properties +++ b/app/core/src/main/resources/messages_da_DK.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF til Billede home.pdfToImage.desc=Konvertér en PDF til et billede. (PNG, JPEG, GIF) pdfToImage.tags=konvertering,img,jpg,billede,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organisér home.pdfOrganiser.desc=Fjern/Omarrangér sider i vilkårlig rækkefølge pdfOrganiser.tags=duplex,lige,ulige,sortér,flyt @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(f.eks. 1,2,8 eller 4,7,12-16 eller 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Tilføj Adgangskode addPassword.header=Tilføj adgangskode (Kryptér) diff --git a/app/core/src/main/resources/messages_de_DE.properties b/app/core/src/main/resources/messages_de_DE.properties index 5762c5dee..83cf59cb3 100644 --- a/app/core/src/main/resources/messages_de_DE.properties +++ b/app/core/src/main/resources/messages_de_DE.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF zu Bild home.pdfToImage.desc=Konvertieren Sie ein PDF in ein Bild (PNG, JPEG, GIF) pdfToImage.tags=konvertierung,img,jpg,bild,foto +home.PDFToVideo.title=PDF zu Video Slideshow +home.PDFToVideo.desc=Konvertieren Sie ein PDF in ein Slideshow-Video. +PDFToVideo.tags=konvertierung,video,slideshow,presentation + home.pdfOrganiser.title=Organisieren home.pdfOrganiser.desc=Seiten entfernen und Seitenreihenfolge ändern pdfOrganiser.tags=duplex,gerade,ungerade,sortieren,verschieben @@ -1260,8 +1264,8 @@ repair.submit=Reparieren flatten.title=Abflachen flatten.header=PDFs reduzieren flatten.flattenOnlyForms=Nur Formulare abflachen -flatten.renderDpi=Rendering DPI (optional, recommended 150 DPI): -flatten.renderDpi.help=Leave blank to use the system default. Higher DPI sharpens output but increases processing time and file size. +flatten.renderDpi=Rendering-DPI (optional, empfohlen 150 DPI): +flatten.renderDpi.help=Leer lassen, um den Systemstandard zu verwenden. Höhere DPI verbessern die Schärfe der Ausgabe, erhöhen jedoch die Verarbeitungszeit und Dateigröße. flatten.submit=Abflachen @@ -1402,8 +1406,8 @@ multiTool.delete=Löschen multiTool.dragDropMessage=Ausgewählte Seite(n) multiTool.undo=Rückgängig machen multiTool.redo=Wiederherstellen -multiTool.duplicate=Duplicate -multiTool.svgNotSupported=SVG files are not supported in Multi Tool and were ignored. +multiTool.duplicate=Duplizieren +multiTool.svgNotSupported=SVG-Dateien werden in Multi Tool nicht unterstützt und wurden ignoriert. #decrypt decrypt.passwordPrompt=Diese Datei ist passwortgeschützt. Bitte geben Sie das Passwort ein: @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(z.B. 1,2,8 oder 4,7,12-16 oder 2n-1) pdfToImage.includeAnnotations=Kommentare, Markierungen usw. einbeziehen +#pdfToVideo +pdfToVideo.title=PDF zu Video Slideshow +pdfToVideo.header=PDF zu Video Slideshow +pdfToVideo.videoFormat=Videoformat +pdfToVideo.secondsPerPage=Sekunden pro Seite +pdfToVideo.resolution=Auflösung +pdfToVideo.watermarkText=Wasserzeichen-Text (leer lassen für kein Wasserzeichen) +pdfToVideo.opacity=Deckkraft des Wasserzeichens (nur angewendet, wenn ein Wasserzeichen-Text angegeben ist) +pdfToVideo.resolutionOriginal=Original (PDF-Seitengröße beibehalten) +pdfToVideo.dpiLabel=DPI (Das Serverlimit beträgt {0} dpi) +pdfToVideo.submit=Konvertieren + + #addPassword addPassword.title=Passwort hinzufügen addPassword.header=Passwort hinzufügen (Verschlüsseln) diff --git a/app/core/src/main/resources/messages_el_GR.properties b/app/core/src/main/resources/messages_el_GR.properties index 97bed7ae4..bb8732c6d 100644 --- a/app/core/src/main/resources/messages_el_GR.properties +++ b/app/core/src/main/resources/messages_el_GR.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF σε εικόνα home.pdfToImage.desc=Μετατροπή PDF σε εικόνα. (PNG, JPEG, GIF) pdfToImage.tags=μετατροπή,εικόνα,jpg,φωτογραφία +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Οργάνωση home.pdfOrganiser.desc=Αφαίρεση/Αναδιάταξη σελίδων σε οποιαδήποτε σειρά pdfOrganiser.tags=duplex,ζυγός,μονός,ταξινόμηση,μετακίνηση @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(π.χ. 1,2,8 ή 4,7,12-16 ή 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Προσθήκη κωδικού addPassword.header=Προσθήκη κωδικού (Κρυπτογράφηση) diff --git a/app/core/src/main/resources/messages_en_GB.properties b/app/core/src/main/resources/messages_en_GB.properties index c0f096ab8..41e0ef4ee 100644 --- a/app/core/src/main/resources/messages_en_GB.properties +++ b/app/core/src/main/resources/messages_en_GB.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF to Image home.pdfToImage.desc=Convert a PDF to a image. (PNG, JPEG, GIF, PSD) pdfToImage.tags=conversion,img,jpg,picture,photo,psd,photoshop +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organise home.pdfOrganiser.desc=Remove/Rearrange pages in any order pdfOrganiser.tags=duplex,even,odd,sort,move @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Add Password addPassword.header=Add password (Encrypt) diff --git a/app/core/src/main/resources/messages_en_US.properties b/app/core/src/main/resources/messages_en_US.properties index d1942c431..287955226 100644 --- a/app/core/src/main/resources/messages_en_US.properties +++ b/app/core/src/main/resources/messages_en_US.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF to Image home.pdfToImage.desc=Convert a PDF to a image. (PNG, JPEG, GIF, PSD) pdfToImage.tags=conversion,img,jpg,picture,photo,psd,photoshop +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organize home.pdfOrganiser.desc=Remove/Rearrange pages in any order pdfOrganiser.tags=duplex,even,odd,sort,move @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Add Password addPassword.header=Add password (Encrypt) diff --git a/app/core/src/main/resources/messages_es_ES.properties b/app/core/src/main/resources/messages_es_ES.properties index f6e0c19ff..139aa5da0 100644 --- a/app/core/src/main/resources/messages_es_ES.properties +++ b/app/core/src/main/resources/messages_es_ES.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF a Imagen home.pdfToImage.desc=Convertir un PDF a una imagen (PNG, JPEG, GIF) pdfToImage.tags=conversión,img,jpg,imagen,fotografía +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organizador home.pdfOrganiser.desc=Eliminar/Reorganizar páginas en cualquier orden pdfOrganiser.tags=doble cara,pares,impares,ordenar,mover @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(por ejemplo 1,2,8 o 4,7,12-16 o 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Añadir contraseña addPassword.header=Añadir contraseña (cifrar) diff --git a/app/core/src/main/resources/messages_eu_ES.properties b/app/core/src/main/resources/messages_eu_ES.properties index e9a661ecf..6ea71e3fe 100644 --- a/app/core/src/main/resources/messages_eu_ES.properties +++ b/app/core/src/main/resources/messages_eu_ES.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDFa irudi bihurtu home.pdfToImage.desc=PDF bat irudi (PNG, JPEG, GIF) bihurtu pdfToImage.tags=conversion,img,jpg,picture,photo,psd,photoshop +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Antolatzailea home.pdfOrganiser.desc=Ezabatu/Berrantolatu orrialdeak edozein ordenatan pdfOrganiser.tags=duplex,even,odd,sort,move @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Gehitu pasahitza addPassword.header=Gehitu pasahitza (enkriptatu) diff --git a/app/core/src/main/resources/messages_fa_IR.properties b/app/core/src/main/resources/messages_fa_IR.properties index fa9e5fd8b..96be59910 100644 --- a/app/core/src/main/resources/messages_fa_IR.properties +++ b/app/core/src/main/resources/messages_fa_IR.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF به تصویر home.pdfToImage.desc=تبدیل یک فایل PDF به یک تصویر. (PNG، JPEG، GIF) pdfToImage.tags=تبدیل،عکس،jpg،تصویر،عکس +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=سازماندهی home.pdfOrganiser.desc=حذف/بازآرایی صفحات به ترتیب دلخواه pdfOrganiser.tags=دوطرفه،زوج،فرد،مرتب‌سازی،جابجایی @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(مثال: 1,2,8 یا 4,7,12-16 یا 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=افزودن گذرواژه addPassword.header=افزودن گذرواژه (رمزنگاری) diff --git a/app/core/src/main/resources/messages_fr_FR.properties b/app/core/src/main/resources/messages_fr_FR.properties index 7a316ff23..aaea7f13d 100644 --- a/app/core/src/main/resources/messages_fr_FR.properties +++ b/app/core/src/main/resources/messages_fr_FR.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF en image home.pdfToImage.desc=Convertissez un PDF en image (PNG, JPEG, GIF). pdfToImage.tags=conversion,img,jpg,image,photo +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organiser home.pdfOrganiser.desc=Supprimez ou réorganisez les pages dans n'importe quel ordre. pdfOrganiser.tags=organiser,recto-verso,duplex,even,odd,sort,move @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(par exemple : 1,2,8 ou 4,7,12-16 ou 2n-1) pdfToImage.includeAnnotations=Inclure les annotations (commentaires, souligné etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Ajouter un mot de passe addPassword.header=Ajouter un mot de passe diff --git a/app/core/src/main/resources/messages_ga_IE.properties b/app/core/src/main/resources/messages_ga_IE.properties index 0032bcf75..fb6f548fb 100644 --- a/app/core/src/main/resources/messages_ga_IE.properties +++ b/app/core/src/main/resources/messages_ga_IE.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF go íomhá home.pdfToImage.desc=Tiontaigh PDF a íomhá. (PNG, JPEG, GIF) pdfToImage.tags=comhshó, img, jpg, pictiúr, grianghraf +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Eagraigh home.pdfOrganiser.desc=Bain/Atheagraigh na leathanaigh in ord ar bith pdfOrganiser.tags=déphléacsacha, cothrom, corr, sórtáil, bogadh @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(m.sh. 1,2,8 nó 4,7,12-16 nó 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Cuir Pasfhocal leis addPassword.header=Cuir pasfhocal leis (Criptigh) diff --git a/app/core/src/main/resources/messages_hi_IN.properties b/app/core/src/main/resources/messages_hi_IN.properties index 85a7f352a..44f9793b2 100644 --- a/app/core/src/main/resources/messages_hi_IN.properties +++ b/app/core/src/main/resources/messages_hi_IN.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF से छवि home.pdfToImage.desc=PDF को छवि में बदलें। (PNG, JPEG, GIF) pdfToImage.tags=रूपांतरण,img,jpg,चित्र,फोटो +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=व्यवस्थित करें home.pdfOrganiser.desc=किसी भी क्रम में पृष्ठ निकालें/पुनर्व्यवस्थित करें pdfOrganiser.tags=डुप्लेक्स,सम,विषम,क्रमबद्ध करें,मूव @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(जैसे 1,2,8 या 4,7,12-16 या 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=पासवर्ड जोड़ें addPassword.header=पासवर्ड जोड़ें (एन्क्रिप्ट) diff --git a/app/core/src/main/resources/messages_hr_HR.properties b/app/core/src/main/resources/messages_hr_HR.properties index 8fd49844e..6166c8e99 100644 --- a/app/core/src/main/resources/messages_hr_HR.properties +++ b/app/core/src/main/resources/messages_hr_HR.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF u sliku home.pdfToImage.desc=Pretvorite PDF u sliku (PNG, JPEG, GIF, PSD). pdfToImage.tags=pretvorba,img,jpg,slika,fotografija,psd,photoshop +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organiziranje home.pdfOrganiser.desc=Uklonite/preuredite stranice u bilo kojem redoslijedu pdfOrganiser.tags=dvostrano,parno,neparno,sortiranje,pomicanje @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(npr. 1,2,8 ili 4,7,12-16 ili 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Dodaj lozinku addPassword.header=Dodaj lozinku (šifriraj) diff --git a/app/core/src/main/resources/messages_hu_HU.properties b/app/core/src/main/resources/messages_hu_HU.properties index e72290c01..6196d851e 100644 --- a/app/core/src/main/resources/messages_hu_HU.properties +++ b/app/core/src/main/resources/messages_hu_HU.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF képpé home.pdfToImage.desc=PDF konvertálása képpé (PNG, JPEG, GIF). pdfToImage.tags=konverzió,kép,jpg,fotó,fénykép +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Rendszerezés home.pdfOrganiser.desc=Oldalak eltávolítása/átrendezése tetszőleges sorrendben pdfOrganiser.tags=duplex,páros,páratlan,rendezés,mozgatás @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(pl. 1,2,8 vagy 4,7,12-16 vagy 2n-1) pdfToImage.includeAnnotations=Megjegyzések belefoglalása (kommentek, kiemelések stb.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Jelszó hozzáadása addPassword.header=Jelszó hozzáadása (Titkosítás) diff --git a/app/core/src/main/resources/messages_id_ID.properties b/app/core/src/main/resources/messages_id_ID.properties index b5d7ff006..8a0d3726e 100644 --- a/app/core/src/main/resources/messages_id_ID.properties +++ b/app/core/src/main/resources/messages_id_ID.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF ke Gambar home.pdfToImage.desc=Mengonversi PDF ke gambar. (PNG, JPEG, GIF) pdfToImage.tags=konversi,img,jpg,gambar,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Mengatur home.pdfOrganiser.desc=Menghapus/Mengatur ulang halaman dalam urutan apa pun pdfOrganiser.tags=dupleks,genap,ganjil,sortir,pindah @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(misalnya 1,2,8 atau 4,7,12-16 atau 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Tambahkan kata sandi addPassword.header=Tambahkan kata sandi (Enkrip) diff --git a/app/core/src/main/resources/messages_it_IT.properties b/app/core/src/main/resources/messages_it_IT.properties index 2384096f7..2b789b4fb 100644 --- a/app/core/src/main/resources/messages_it_IT.properties +++ b/app/core/src/main/resources/messages_it_IT.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=Da PDF a immagine home.pdfToImage.desc=Converti un PDF in un'immagine. (PNG, JPEG, GIF) pdfToImage.tags=conversione,img,jpg,immagine,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organizza home.pdfOrganiser.desc=Rimuovi/Riordina le pagine in qualsiasi ordine. pdfOrganiser.tags=duplex,pari,dispari,ordinamento,spostamento @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(es. 1,2,8 o 4,7,12-16 o 2n-1) pdfToImage.includeAnnotations=Includi annotazioni (commenti, evidenziazioni, ecc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Aggiungi Password addPassword.header=Aggiungi password (crittografa) diff --git a/app/core/src/main/resources/messages_ja_JP.properties b/app/core/src/main/resources/messages_ja_JP.properties index 1514d5a58..85605c0e5 100644 --- a/app/core/src/main/resources/messages_ja_JP.properties +++ b/app/core/src/main/resources/messages_ja_JP.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDFを画像に変換 home.pdfToImage.desc=PDFを画像 (PNG, JPEG, GIF) に変換します。 pdfToImage.tags=conversion,img,jpg,picture,photo,psd,photoshop +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=整理 home.pdfOrganiser.desc=ページの削除/並べ替えします。 pdfOrganiser.tags=duplex,even,odd,sort,move @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(例:1,2,8、4,7,12-16、2n-1) pdfToImage.includeAnnotations=注釈(コメント、ハイライトなど)を含める +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=パスワードの追加 addPassword.header=パスワードの追加(暗号化) diff --git a/app/core/src/main/resources/messages_ko_KR.properties b/app/core/src/main/resources/messages_ko_KR.properties index 1bd4a9529..cbe290415 100644 --- a/app/core/src/main/resources/messages_ko_KR.properties +++ b/app/core/src/main/resources/messages_ko_KR.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF를 이미지로 home.pdfToImage.desc=PDF를 이미지로 변환합니다. (PNG, JPEG, GIF) pdfToImage.tags=변환,이미지,jpg,사진 +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=정리 home.pdfOrganiser.desc=원하는 순서로 페이지 제거/재배치 pdfOrganiser.tags=양면,짝수,홀수,정렬,이동 @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(예: 1,2,8 또는 4,7,12-16 또는 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=비밀번호 추가 addPassword.header=비밀번호 추가 (암호화) diff --git a/app/core/src/main/resources/messages_ml_IN.properties b/app/core/src/main/resources/messages_ml_IN.properties index 42a1e9b72..f22b73eb7 100644 --- a/app/core/src/main/resources/messages_ml_IN.properties +++ b/app/core/src/main/resources/messages_ml_IN.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF ചിത്രത്തിലേക്ക് home.pdfToImage.desc=ഒരു PDF ചിത്രത്തിലേക്ക് മാറ്റുക. (PNG, JPEG, GIF) pdfToImage.tags=പരിവർത്തനം,img,jpg,ചിത്രം,ഫോട്ടോ +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=ക്രമീകരിക്കുക home.pdfOrganiser.desc=ഏത് ക്രമത്തിലും പേജുകൾ നീക്കം ചെയ്യുക/പുനഃക്രമീകരിക്കുക pdfOrganiser.tags=ഡ്യൂപ്ലെക്സ്,ഇരട്ട,ഒറ്റ,അടുക്കുക,നീക്കുക @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(ഉദാ. 1,2,8 അല്ലെങ്കിൽ 4,7,12-1 pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=പാസ്വേഡ് ചേർക്കുക addPassword.header=പാസ്വേഡ് ചേർക്കുക (എൻക്രിപ്റ്റ് ചെയ്യുക) diff --git a/app/core/src/main/resources/messages_nl_NL.properties b/app/core/src/main/resources/messages_nl_NL.properties index 729f49cb6..6bbecb2df 100644 --- a/app/core/src/main/resources/messages_nl_NL.properties +++ b/app/core/src/main/resources/messages_nl_NL.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF naar Afbeelding home.pdfToImage.desc=Converteer een PDF naar een afbeelding. (PNG, JPEG, GIF) pdfToImage.tags=conversie,img,jpg,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organiseren home.pdfOrganiser.desc=Verwijder/herschik pagina's in een volgorde naar keus pdfOrganiser.tags=duplex,even oneven,sorteren,verplaatsen @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(bijv. 1,2,8 of 4,7,12-16 of 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Wachtwoord toevoegen addPassword.header=Wachtwoord toevoegen (Versleutelen) diff --git a/app/core/src/main/resources/messages_no_NB.properties b/app/core/src/main/resources/messages_no_NB.properties index 486cd3ce4..5aaaa8222 100644 --- a/app/core/src/main/resources/messages_no_NB.properties +++ b/app/core/src/main/resources/messages_no_NB.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF til Bilde home.pdfToImage.desc=Konverter en PDF til et bilde. (PNG, JPEG, GIF) pdfToImage.tags=konvertering,bilde,jpg,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organiser home.pdfOrganiser.desc=Fjern/omorganiser sider i hvilken som helst rekkefølge pdfOrganiser.tags=dupleks,par,single,sorter,flytt @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(f.eks. 1,2,8 eller 4,7,12-16 eller 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Legg til passord addPassword.header=Legg til passord (Krypter) diff --git a/app/core/src/main/resources/messages_pl_PL.properties b/app/core/src/main/resources/messages_pl_PL.properties index 78b728673..3316c2bf2 100644 --- a/app/core/src/main/resources/messages_pl_PL.properties +++ b/app/core/src/main/resources/messages_pl_PL.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF na Obraz home.pdfToImage.desc=Konwertuj plik PDF na obraz (PNG, JPEG, GIF). pdfToImage.tags=konwersja,img,jpg,obraz,zdjęcie +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Uporządkuj home.pdfOrganiser.desc=Usuń/Zmień kolejność stron w dowolnej kolejności pdfOrganiser.tags=duplex,parzyste,nieparzyste,sortuj,przenieś @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(przykład 1,2,8 lub 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Dodaj hasło addPassword.header=Dodaj hasło (zaszyfruj) diff --git a/app/core/src/main/resources/messages_pt_BR.properties b/app/core/src/main/resources/messages_pt_BR.properties index b79592ed0..8d95de847 100644 --- a/app/core/src/main/resources/messages_pt_BR.properties +++ b/app/core/src/main/resources/messages_pt_BR.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF para Imagem home.pdfToImage.desc=Converter PDF em uma imagem (PNG, JPG, GIF e outros). pdfToImage.tags=conversão,img,jpg,imagem,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organizar Páginas home.pdfOrganiser.desc=Remover/reorganizar as páginas de diversas formas diferentes. pdfOrganiser.tags=duplex,par,ímpar,ordenar,mover @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(por exemplo 1,2,8 ou 4,7,12-16 ou 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Proteger PDF addPassword.header=Proteger PDF (Criptografar) diff --git a/app/core/src/main/resources/messages_pt_PT.properties b/app/core/src/main/resources/messages_pt_PT.properties index 3bb670243..e6767437b 100644 --- a/app/core/src/main/resources/messages_pt_PT.properties +++ b/app/core/src/main/resources/messages_pt_PT.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF para Imagem home.pdfToImage.desc=Converter um PDF para uma imagem. (PNG, JPEG, GIF) pdfToImage.tags=conversão,img,jpg,imagem,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organizar home.pdfOrganiser.desc=Remover/Reorganizar páginas em qualquer ordem pdfOrganiser.tags=duplex,par,ímpar,ordenar,mover @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(ex. 1,2,8 ou 4,7,12-16 ou 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Adicionar Palavra-passe addPassword.header=Adicionar palavra-passe (Encriptar) diff --git a/app/core/src/main/resources/messages_ro_RO.properties b/app/core/src/main/resources/messages_ro_RO.properties index 9a378f501..606b15380 100644 --- a/app/core/src/main/resources/messages_ro_RO.properties +++ b/app/core/src/main/resources/messages_ro_RO.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF în Imagine home.pdfToImage.desc=Convertește un fișier PDF în imagine (PNG, JPEG, GIF). pdfToImage.tags=conversie,img,jpg,poză,fotografie +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organizează home.pdfOrganiser.desc=Elimină/rearanjează pagini în orice ordine pdfOrganiser.tags=duplex,par,impar,sortează,mută @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(ex. 1,2,8 sau 4,7,12-16 sau 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Adaugă parolă addPassword.header=Adaugă o parolă (Criptare) diff --git a/app/core/src/main/resources/messages_ru_RU.properties b/app/core/src/main/resources/messages_ru_RU.properties index 95f1218fe..eb6e63668 100644 --- a/app/core/src/main/resources/messages_ru_RU.properties +++ b/app/core/src/main/resources/messages_ru_RU.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF в изображение home.pdfToImage.desc=Преобразование PDF в изображение (PNG, JPEG, GIF). pdfToImage.tags=png,jpeg,gif,конвертация,изображение,картинка,фото +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Организация home.pdfOrganiser.desc=Удаление/переупорядочивание страниц в любом порядке pdfOrganiser.tags=двусторонняя печать,четные,нечетные,сортировка,перемещение @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(например, 1,2,8 или 4,7,12-16 или 2n-1) pdfToImage.includeAnnotations=Добавьте аннотации (комментарии, основные моменты и т.д.). +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Добавить пароль addPassword.header=Добавить пароль (Шифрование) diff --git a/app/core/src/main/resources/messages_sk_SK.properties b/app/core/src/main/resources/messages_sk_SK.properties index 702cdb1de..34499c9a9 100644 --- a/app/core/src/main/resources/messages_sk_SK.properties +++ b/app/core/src/main/resources/messages_sk_SK.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF na obrázok home.pdfToImage.desc=Konvertujte PDF na obrázok. (PNG, JPEG, GIF) pdfToImage.tags=konverzia,img,jpg,obrázok,fotografia +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organizovať home.pdfOrganiser.desc=Odstráňte/preusporiadajte stránky v ľubovoľnom poradí pdfOrganiser.tags=duplex,nepárne,párne,zoradiť,posunúť @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(napr. 1,2,8 alebo 4,7,12-16 alebo 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Pridať heslo addPassword.header=Pridať heslo (Zašifrovať) diff --git a/app/core/src/main/resources/messages_sl_SI.properties b/app/core/src/main/resources/messages_sl_SI.properties index fb1fd055f..0d42cad53 100644 --- a/app/core/src/main/resources/messages_sl_SI.properties +++ b/app/core/src/main/resources/messages_sl_SI.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF v sliko home.pdfToImage.desc=Pretvori PDF v sliko. (PNG, JPEG, GIF) pdfToImage.tags=pretvorba,img,jpg,slika,fotografija +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organiziraj home.pdfOrganiser.desc=Odstrani/Prerazporedi strani v poljubnem vrstnem redu pdfOrganiser.tags=dvostranski,sodi,lihi,razvrsti,premakni @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(npr. 1,2,8 ali 4,7,12-16 ali 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Dodaj geslo addPassword.header=Dodaj geslo (Šifriraj) diff --git a/app/core/src/main/resources/messages_sr_LATN_RS.properties b/app/core/src/main/resources/messages_sr_LATN_RS.properties index 24fdb5293..25ee4bf0b 100644 --- a/app/core/src/main/resources/messages_sr_LATN_RS.properties +++ b/app/core/src/main/resources/messages_sr_LATN_RS.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF u Sliku home.pdfToImage.desc=Konvertovanje PDF u sliku (PNG, JPEG, GIF) pdfToImage.tags=konverzija,img,jpg,slika,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Organizacija home.pdfOrganiser.desc=Uklanjanje/premeštanje stranica po bilo kom redosledu pdfOrganiser.tags=dupleks,parne,neparne,sortiranje,pomeranje @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(npr. 1,2,8 ili 4,7,12-16 ili 2n-1) pdfToImage.includeAnnotations=Uključi napomene (komentare, isticanja itd.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Dodaj šifru addPassword.header=Dodaj šifru (enkripcija) diff --git a/app/core/src/main/resources/messages_sv_SE.properties b/app/core/src/main/resources/messages_sv_SE.properties index 946eff3bb..a56dfa02c 100644 --- a/app/core/src/main/resources/messages_sv_SE.properties +++ b/app/core/src/main/resources/messages_sv_SE.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF till bild home.pdfToImage.desc=Konvertera en PDF till en bild. (PNG, JPEG, GIF) pdfToImage.tags=konvertering,img,jpg,bild,foto +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Ordna home.pdfOrganiser.desc=Ta bort/ordna om sidor i valfri ordning pdfOrganiser.tags=duplex,jämn,udda,sortera,flytta @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(t.ex. 1,2,8 eller 4,7,12-16 eller 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Lägg till lösenord addPassword.header=Lägg till lösenord (kryptera) diff --git a/app/core/src/main/resources/messages_th_TH.properties b/app/core/src/main/resources/messages_th_TH.properties index b52fea419..0c7fafe64 100644 --- a/app/core/src/main/resources/messages_th_TH.properties +++ b/app/core/src/main/resources/messages_th_TH.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF เป็นรูปภาพ home.pdfToImage.desc=แปลง PDF เป็นรูปภาพ (PNG, JPEG, GIF) pdfToImage.tags=การแปลง, รูปภาพ, JPG, ภาพ, รูปถ่าย +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=จัดระเบียบ home.pdfOrganiser.desc=ลบ/จัดเรียงหน้าต่างๆ ในลำดับที่ต้องการ pdfOrganiser.tags=สองหน้า, คู่ขนาน, เรียงลำดับ, เคลื่อนย้าย @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(เช่น 1,2,8 หรือ 4,7,12-16 หรือ 2 pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=เพิ่มรหัสผ่าน addPassword.header=เพิ่มรหัสผ่าน (เข้ารหัส) diff --git a/app/core/src/main/resources/messages_tr_TR.properties b/app/core/src/main/resources/messages_tr_TR.properties index 276d0b99f..ee7775758 100644 --- a/app/core/src/main/resources/messages_tr_TR.properties +++ b/app/core/src/main/resources/messages_tr_TR.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF'den Resme home.pdfToImage.desc=PDF'yi bir resme dönüştürün. (PNG, JPEG, GIF) pdfToImage.tags=dönüşüm,img,jpg,fotoğraf,resim +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Düzenle home.pdfOrganiser.desc=Sayfaları herhangi bir sırayla kaldırın/düzenleyin pdfOrganiser.tags=çift,çift,yan,yana,sırala,taşı @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(örneğin 1,2,8 veya 4,7,12-16 ya da 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Parola Ekle addPassword.header=Parola Ekle (Şifrele) diff --git a/app/core/src/main/resources/messages_uk_UA.properties b/app/core/src/main/resources/messages_uk_UA.properties index cf493d79e..da59001a2 100644 --- a/app/core/src/main/resources/messages_uk_UA.properties +++ b/app/core/src/main/resources/messages_uk_UA.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF в зображення home.pdfToImage.desc=Перетворення PDF в зображення. (PNG, JPEG, GIF) pdfToImage.tags=конвертація,зображення,jpg,картинка,фото +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Реорганізація home.pdfOrganiser.desc=Видалення/перестановка сторінок у будь-якому порядку pdfOrganiser.tags=двосторонній друк,парні,непарні,сортування,переміщення @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(наприклад 1,2,8 або 4,7,12-16 або 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Додати пароль addPassword.header=Додати пароль (зашифрувати) diff --git a/app/core/src/main/resources/messages_vi_VN.properties b/app/core/src/main/resources/messages_vi_VN.properties index 4aa2426c9..75aaf6b27 100644 --- a/app/core/src/main/resources/messages_vi_VN.properties +++ b/app/core/src/main/resources/messages_vi_VN.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF sang Hình ảnh home.pdfToImage.desc=Chuyển đổi PDF sang hình ảnh. (PNG, JPEG, GIF) pdfToImage.tags=chuyển đổi,img,jpg,hình ảnh,ảnh +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=Sắp xếp home.pdfOrganiser.desc=Xóa/Sắp xếp lại trang theo bất kỳ thứ tự nào pdfOrganiser.tags=duplex,chẵn,lẻ,sắp xếp,di chuyển @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(ví dụ: 1,2,8 hoặc 4,7,12-16 hoặc 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=Thêm mật khẩu addPassword.header=Thêm mật khẩu (Mã hóa) diff --git a/app/core/src/main/resources/messages_zh_CN.properties b/app/core/src/main/resources/messages_zh_CN.properties index 002249c1b..cd6596b3c 100644 --- a/app/core/src/main/resources/messages_zh_CN.properties +++ b/app/core/src/main/resources/messages_zh_CN.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=转换 PDF 到图像 home.pdfToImage.desc=将 PDF 转换为图像(PNG、JPEG、GIF)。 pdfToImage.tags=转换、图像、JPG、图片、照片 +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=整理 home.pdfOrganiser.desc=按任意顺序删除/重新排列页面。 pdfOrganiser.tags=双面、偶数、奇数、排序、移动 @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(例如:1,2,8 或 4,7,12-16 或 2n-1) pdfToImage.includeAnnotations=Include annotations (comments, highlights etc.) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=添加密码 addPassword.header=添加密码(加密)。 diff --git a/app/core/src/main/resources/messages_zh_TW.properties b/app/core/src/main/resources/messages_zh_TW.properties index bc7fbbe90..4e3384a55 100644 --- a/app/core/src/main/resources/messages_zh_TW.properties +++ b/app/core/src/main/resources/messages_zh_TW.properties @@ -628,6 +628,10 @@ home.pdfToImage.title=PDF 轉圖片 home.pdfToImage.desc=將 PDF 轉換為圖片(PNG、JPEG、GIF)。 pdfToImage.tags=轉換,img,jpg,圖片,照片 +home.PDFToVideo.title=PDF to Video Slideshow +home.PDFToVideo.desc=Convert a PDF into a slideshow-style video. +PDFToVideo.tags=conversion,video,slideshow,presentation + home.pdfOrganiser.title=整理 home.pdfOrganiser.desc=移除或重新排列頁面順序 pdfOrganiser.tags=雙面,偶數,奇數,排序,移動 @@ -1512,6 +1516,19 @@ pdfToImage.placeholder=(例如 1,2,8 或 4,7,12-16 或 2n-1) pdfToImage.includeAnnotations=包含註釋(評論、醒目提示等) +#pdfToVideo +pdfToVideo.title=PDF to Video Slideshow +pdfToVideo.header=PDF to Video Slideshow +pdfToVideo.videoFormat=Video format +pdfToVideo.secondsPerPage=Seconds per page +pdfToVideo.resolution=Resolution +pdfToVideo.watermarkText=Watermark Text (empty for no watermark) +pdfToVideo.opacity=Opacity of the watermark (only applied if a watermark text is specified) +pdfToVideo.resolutionOriginal=Original (keep PDF page size) +pdfToVideo.dpiLabel=DPI (The server limit is {0} dpi) +pdfToVideo.submit=Convert + + #addPassword addPassword.title=新增密碼 addPassword.header=新增密碼(加密) diff --git a/app/core/src/main/resources/templates/convert/pdf-to-video.html b/app/core/src/main/resources/templates/convert/pdf-to-video.html new file mode 100644 index 000000000..e3307af70 --- /dev/null +++ b/app/core/src/main/resources/templates/convert/pdf-to-video.html @@ -0,0 +1,84 @@ + + + + + + + + + + +
+
+ +

+
+
+
+
+ movie + +
+

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/app/core/src/main/resources/templates/fragments/navElements.html b/app/core/src/main/resources/templates/fragments/navElements.html index d235dbbdf..bbf09985e 100644 --- a/app/core/src/main/resources/templates/fragments/navElements.html +++ b/app/core/src/main/resources/templates/fragments/navElements.html @@ -113,6 +113,9 @@
+
+
@@ -175,6 +178,9 @@
+
+
diff --git a/app/core/src/main/resources/templates/home-legacy.html b/app/core/src/main/resources/templates/home-legacy.html index ea4cc0295..33441fe95 100644 --- a/app/core/src/main/resources/templates/home-legacy.html +++ b/app/core/src/main/resources/templates/home-legacy.html @@ -195,6 +195,9 @@
+
+
diff --git a/testing/allEndpointsRemovedSettings.yml b/testing/allEndpointsRemovedSettings.yml index 04cb000cd..014556fc0 100644 --- a/testing/allEndpointsRemovedSettings.yml +++ b/testing/allEndpointsRemovedSettings.yml @@ -182,6 +182,7 @@ processExecutor: calibreSessionLimit: 1 ghostscriptSessionLimit: 8 ocrMyPdfSessionLimit: 2 + ffmpegSessionLimit: 2 timeoutMinutes: # Process executor timeout in minutes libreOfficetimeoutMinutes: 30 pdfToHtmltimeoutMinutes: 20 @@ -193,3 +194,4 @@ processExecutor: qpdfTimeoutMinutes: 30 ghostscriptTimeoutMinutes: 30 ocrMyPdfTimeoutMinutes: 30 + ffmpegTimeoutMinutes: 30