From 2d973cb20752ef525314348eb255cd62de3ceddb Mon Sep 17 00:00:00 2001 From: Kyle Lieber Date: Thu, 31 Aug 2023 00:59:42 -0500 Subject: [PATCH] feat: support 3gp --- Dockerfile | 2 +- default-config.json | 5 +++- lib/support/file-utils.js | 40 ++++++++++++++++++++++++++++++-- package-lock.json | 49 +++++++++++++++++++++++++++++++++++---- package.json | 1 + 5 files changed, 89 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 49380ff2..71c9b607 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ WORKDIR /usr/src/app COPY package*.json ./ -RUN apt-get update && apt-get install -y libvips && apt-get clean +RUN apt-get update && apt-get install -y libvips ffmpeg && apt-get clean RUN npm ci --platform=linux --arch=x64 --only=production --ignore-scripts RUN npm uninstall sharp && npm install --platform=linux --arch=x64 sharp diff --git a/default-config.json b/default-config.json index 720a6f30..5057596d 100644 --- a/default-config.json +++ b/default-config.json @@ -20,7 +20,10 @@ "target": "/media/photo" }, { - "extensions": ["mp4", "mov"], + "extensions": ["mp4", "mov", "3gp"], + "conversions": { + "3gp": "mp4" + }, "target": "/media/video" } ] diff --git a/lib/support/file-utils.js b/lib/support/file-utils.js index 4706eb67..41240f25 100644 --- a/lib/support/file-utils.js +++ b/lib/support/file-utils.js @@ -5,6 +5,12 @@ const DropboxContentHasher = require('../provider/dropbox/dropbox-content-hasher const logger = require('./logger').create('lib/support/file-utils'); const config = require('../config'); const sharp = require('sharp'); +const ffmpeg = require('fluent-ffmpeg'); + +const CONVERTERS = { + jpg: convertImage, + mp4: convertVideo +}; async function createFileInfo(sourceFile, targetDirectory) { const timestamp = await extractDate(sourceFile); @@ -80,8 +86,13 @@ async function moveFile(sourceFile, targetDirectory, conversions) { if (!config.dry_run) { await mkdirp(target.dirname); if (target.conversion) { - let buffer = await fs.promises.readFile(sourceFile); - await sharp(buffer).toFormat(target.extension).toFile(target.name); + let convert = CONVERTERS[target.extension]; + + if (!convert) { + throw new Error(`conversion not supported: ${target.extension}`); + } + + await convert(sourceFile, target); } else { await fs.promises.copyFile(sourceFile, target.name); } @@ -106,6 +117,31 @@ async function hash(filename) { return hasher.digest('hex'); } +async function convertImage(sourceFile, target) { + let buffer = await fs.promises.readFile(sourceFile); + await sharp(buffer).toFormat(target.extension).toFile(target.name); +} + +async function convertVideo(sourceFile, target) { + await new Promise((resolve, reject) => { + ffmpeg({ source: sourceFile }) + .on('progress', (progress) => { + logger.verbose(`[ffmpeg] ${JSON.stringify(progress)}`); + }) + .on('error', (err) => { + logger.verbose(`[ffmpeg] error: ${err.message}`); + reject(err); + }) + .on('end', () => { + logger.verbose('[ffmpeg] finished'); + resolve(); + }) + .withAudioCodec('libmp3lame') + .toFormat(target.extension) + .saveToFile(target.name); + }); +} + module.exports = { createFileInfo: createFileInfo, moveFile: moveFile diff --git a/package-lock.json b/package-lock.json index f9ff20de..339ba316 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "dropbox": "10.34.0", "ffprobe": "1.1.2", "ffprobe-static": "3.1.0", + "fluent-ffmpeg": "2.1.2", "node-exiftool": "2.3.0", "node-fetch": "3.3.2", "rc": "1.2.8", @@ -6683,6 +6684,29 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "node_modules/fluent-ffmpeg": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz", + "integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==", + "dependencies": { + "async": ">=0.2.9", + "which": "^1.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fluent-ffmpeg/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -7806,8 +7830,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/issue-parser": { "version": "6.0.0", @@ -22220,6 +22243,25 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "fluent-ffmpeg": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz", + "integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==", + "requires": { + "async": ">=0.2.9", + "which": "^1.1.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -23021,8 +23063,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "issue-parser": { "version": "6.0.0", diff --git a/package.json b/package.json index 41bfcf01..32304e4c 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "dropbox": "10.34.0", "ffprobe": "1.1.2", "ffprobe-static": "3.1.0", + "fluent-ffmpeg": "2.1.2", "node-exiftool": "2.3.0", "node-fetch": "3.3.2", "rc": "1.2.8",