change video/audio handling, allows "audio" files with a video mime type to be uploaded properly, and get treated like audio file. might need some testing to make sure nothing broke :)

merge-requests/208/head
Thomas Lynch 4 years ago
parent 01d11f9491
commit 8629143610
  1. 8
      controllers/forms/makepost.js
  2. 115
      models/forms/makepost.js

@ -3,7 +3,8 @@
const makePost = require(__dirname+'/../../models/forms/makepost.js')
, deleteTempFiles = require(__dirname+'/../../helpers/files/deletetempfiles.js')
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js')
, { globalLimits, disableOnionFilePosting } = require(__dirname+'/../../configs/main.js')
, pruneFiles = require(__dirname+'/../../schedules/prune.js')
, { pruneImmediately, globalLimits, disableOnionFilePosting } = require(__dirname+'/../../configs/main.js')
, { Files } = require(__dirname+'/../../db/');
module.exports = async (req, res, next) => {
@ -88,7 +89,10 @@ module.exports = async (req, res, next) => {
} catch (err) {
await deleteTempFiles(req).catch(e => console.error);
if (res.locals.numFiles > 0) {
await Files.decrement(req.files.file.filter(x => x.inced === true && x.filename != null).map(x => x.filename)).catch(e => console.error);
const incedFiles = req.files.file.filter(x => x.inced === true && x.filename != null);
const incedFileNames = incedFiles.map(x => x.filename);
await Files.decrement(incedFileNames).catch(e => console.error);
await pruneFiles(incedFileNames);
}
return next(err);
}

@ -241,13 +241,29 @@ ${res.locals.numFiles > 0 ? req.files.file.map(f => f.name+'|'+(f.phash || '')).
};
//type and subtype
const [type, subtype] = processedFile.mimetype.split('/');
let imageData;
let firstFrameOnly = true;
if (type === 'image') {
let [type, subtype] = processedFile.mimetype.split('/');
//check if already exists
const existsFull = await pathExists(`${uploadDirectory}/file/${processedFile.filename}`);
processedFile.sizeString = formatSize(processedFile.size)
const saveFull = async () => {
if (!existsFull) {
await Files.increment(processedFile);
req.files.file[i].inced = true;
await moveUpload(file, processedFile.filename, 'file');
}
}
if (mimeTypes.other.has(processedFile.mimetype)) {
//"other" mimes from config, overrides main type to avoid codec issues in browser or ffmpeg for unsupported filetypes
processedFile.hasThumb = false;
processedFile.attachment = true;
await saveFull();
} else {
const existsThumb = await pathExists(`${uploadDirectory}/file/thumb-${processedFile.hash}${processedFile.thumbextension}`);
switch (type) {
case 'image': {
processedFile.thumbextension = thumbExtension;
///detect images with opacity for PNG thumbnails, set thumbextension before increment
let imageData;
try {
imageData = await imageIdentify(req.files.file[i].tempFilePath, null, true);
} catch (e) {
@ -258,8 +274,8 @@ ${res.locals.numFiles > 0 ? req.files.file.map(f => f.name+'|'+(f.phash || '')).
'redirect': redirect
});
}
if (imageData['Channel Statistics'] && imageData['Channel Statistics']['Opacity']) {//does this depend on GM version or anything?
if (imageData['Channel Statistics'] && imageData['Channel Statistics']['Opacity']) {
//does this depend on GM version or anything?
const opacityMaximum = imageData['Channel Statistics']['Opacity']['Maximum'];
if (opacityMaximum !== '0.00 (0.0000)') {
processedFile.thumbextension = '.png';
@ -272,6 +288,7 @@ ${res.locals.numFiles > 0 ? req.files.file.map(f => f.name+'|'+(f.phash || '')).
processedFile.hasThumb = !(mimeTypes.allowed(file.mimetype, {image: true})
&& subtype !== 'png'
&& lteThumbSize);
let firstFrameOnly = true;
if (processedFile.hasThumb //if it needs thumbnailing
&& (!lteThumbSize //and its big enough
&& file.mimetype === 'image/gif' //and its a gif
@ -280,65 +297,28 @@ ${res.locals.numFiles > 0 ? req.files.file.map(f => f.name+'|'+(f.phash || '')).
firstFrameOnly = false;
processedFile.thumbextension = '.gif';
}
} else if (type === 'audio') {
if (audioThumbnails) {
// waveform has a transparent background, so force png
processedFile.thumbextension = '.png';
}
} else {
processedFile.thumbextension = thumbExtension;
}
//increment file count
await Files.increment(processedFile);
req.files.file[i].inced = true;
//check if already exists
const existsFull = await pathExists(`${uploadDirectory}/file/${processedFile.filename}`);
processedFile.sizeString = formatSize(processedFile.size)
if (mimeTypes.other.has(processedFile.mimetype)) {
//"other" mimes from config, overrides main type to avoid codec issues in browser or ffmpeg for unsupported filetypes
processedFile.hasThumb = false;
processedFile.attachment = true;
if (!existsFull) {
await moveUpload(file, processedFile.filename, 'file');
}
} else {
const existsThumb = await pathExists(`${uploadDirectory}/file/thumb-${processedFile.hash}${processedFile.thumbextension}`);
switch (type) {
case 'image': {
if (!existsFull) {
await moveUpload(file, processedFile.filename, 'file');
}
await saveFull();
if (!existsThumb) {
await imageThumbnail(processedFile, firstFrameOnly);
}
processedFile = fixGifs(processedFile);
break;
}
case 'video': {
case 'audio':
case 'video':
//video metadata
const videoData = await ffprobe(req.files.file[i].tempFilePath, null, true);
videoData.streams = videoData.streams.filter(stream => stream.width != null); //filter to only video streams or something with a resolution
if (videoData.streams.length <= 0) {
//corrupt, or audio only?
await deleteTempFiles(req).catch(e => console.error);
return dynamicResponse(req, res, 400, 'message', {
'title': 'Bad request',
'message': 'Audio only video file not supported',
'redirect': redirect
});
}
processedFile.duration = videoData.format.duration;
processedFile.durationString = timeUtils.durationString(videoData.format.duration*1000);
processedFile.geometry = {width: videoData.streams[0].coded_width, height: videoData.streams[0].coded_height};
const audioVideoData = await ffprobe(req.files.file[i].tempFilePath, null, true);
processedFile.duration = audioVideoData.format.duration;
processedFile.durationString = timeUtils.durationString(audioVideoData.format.duration*1000);
const videoStreams = audioVideoData.streams.filter(stream => stream.width != null); //filter to only video streams or something with a resolution
if (videoStreams.length > 0) {
processedFile.thumbextension = thumbExtension;
processedFile.geometry = {width: videoStreams[0].coded_width, height: videoStreams[0].coded_height};
processedFile.geometryString = `${processedFile.geometry.width}x${processedFile.geometry.height}`
processedFile.hasThumb = true;
if (!existsFull) {
await moveUpload(file, processedFile.filename, 'file');
}
await saveFull();
if (!existsThumb) {
const numFrames = videoData.streams[0].nb_frames;
const numFrames = videoStreams[0].nb_frames;
if (numFrames === 'N/A' && subtype === 'webm') {
await videoThumbnail(processedFile, processedFile.geometry, videoThumbPercentage+'%');
let videoThumbStat = null;
@ -352,28 +332,19 @@ ${res.locals.numFiles > 0 ? req.files.file.map(f => f.name+'|'+(f.phash || '')).
await videoThumbnail(processedFile, processedFile.geometry, ((numFrames === 'N/A' || numFrames <= 1) ? 0 : videoThumbPercentage+'%'));
}
}
break;
}
case 'audio': {
//audio metadata
const audioData = await ffprobe(req.files.file[i].tempFilePath, null, true);
processedFile.duration = audioData.format.duration;
processedFile.durationString = timeUtils.durationString(audioData.format.duration*1000);
} else {
//audio file, or video with only audio streams
type = 'audio';
processedFile.mimetype = `audio/${subtype}`;
processedFile.thumbextension = '.png';
processedFile.hasThumb = audioThumbnails;
if (!existsFull) {
await moveUpload(file, processedFile.filename, 'file');
}
if (audioThumbnails) {
// audio thumbnail is always thumbSize x thumbSize
processedFile.geometry = {
thumbwidth: thumbSize, thumbheight: thumbSize,
};
processedFile.geometry = { thumbwidth: thumbSize, thumbheight: thumbSize };
await saveFull();
if (!existsThumb) {
await audioThumbnail(processedFile);
}
}
break;
}
default:
throw new Error(`invalid file mime type: ${processedFile}`);
}

Loading…
Cancel
Save