audio thumbnails

merge-requests/208/head
some random guy 4 years ago
parent 2adff07989
commit da8522faec
  1. 5
      configs/main.js.example
  2. 13
      gulp/res/js/expand.js
  3. 22
      helpers/files/audiothumbnail.js
  4. 30
      models/forms/makepost.js
  5. 4
      views/mixins/catalogtile.pug
  6. 4
      views/mixins/post.pug

@ -58,7 +58,7 @@ module.exports = {
distortion: 9,
},
/* dnsbl, will add a small delay for uncached requests. You could also install some
/* dnsbl, will add a small delay for uncached requests. You could also install some
kind of dns cache e.g. unbound to improve performance. DNSBL only checked for posting */
dnsbl: {
enabled: false,
@ -127,6 +127,9 @@ module.exports = {
//if animatedGifThumbnails is true, use ffmpeg for better animated gif thumbnailing. RECOMMENDED
ffmpegGifThumbnails: true,
//generate waveform thumbnails for audio
audioThumbnails: false,
//max thumb dimensions (square) in px
thumbSize: 250,

@ -165,8 +165,17 @@ window.addEventListener('DOMContentLoaded', (event) => {
expandedElement.controls = 'true';
source = document.createElement('source');
expandedElement.appendChild(source);
expandedElement.style.minWidth = fileAnchor.offsetWidth+'px';
expandedElement.style.minHeight = fileAnchor.offsetHeight+'px';
console.log(this);
if (type === 'audio' && thumbElement.nodeName === 'IMG') {
expandedElement.style.backgroundImage =
`url("${encodeURI(thumbElement.src)}")`;
expandedElement.style.backgroundRepeat = 'no-repeat';
expandedElement.style.minWidth = thumbElement.width+'px';
expandedElement.style.minHeight = thumbElement.height+'px';
} else {
expandedElement.style.minWidth = fileAnchor.offsetWidth+'px';
expandedElement.style.minHeight = fileAnchor.offsetHeight+'px';
}
pfs.appendChild(expandedElement);
fileAnchor.appendChild(closeSpan);
toggle(thumbElement, expandedElement, fileName, pfs);

@ -0,0 +1,22 @@
const ffmpeg = require('fluent-ffmpeg')
, { thumbSize } = require(__dirname+'/../../configs/main.js')
, uploadDirectory = require(__dirname+'/uploadDirectory.js');
module.exports = (file) => {
return new Promise((resolve, reject) => {
ffmpeg(`${uploadDirectory}/file/${file.filename}`)
.on('end', () => {
return resolve();
})
.on('error', function(err, stdout, stderr) {
return reject(err);
})
.complexFilter([{
filter: 'showwavespic',
options: { split_channels: 1, s: `${thumbSize}x${thumbSize}` }
}])
.save(`${uploadDirectory}/file/thumb-${file.hash}${file.thumbextension}`);
});
};

@ -17,6 +17,7 @@ const path = require('path')
, imageThumbnail = require(__dirname+'/../../helpers/files/imagethumbnail.js')
, imageIdentify = require(__dirname+'/../../helpers/files/imageidentify.js')
, videoThumbnail = require(__dirname+'/../../helpers/files/videothumbnail.js')
, audioThumbnail = require(__dirname+'/../../helpers/files/audiothumbnail.js')
, ffprobe = require(__dirname+'/../../helpers/files/ffprobe.js')
, formatSize = require(__dirname+'/../../helpers/files/formatsize.js')
, deleteTempFiles = require(__dirname+'/../../helpers/files/deletetempfiles.js')
@ -25,7 +26,8 @@ const path = require('path')
, deletePosts = require(__dirname+'/deletepost.js')
, spamCheck = require(__dirname+'/../../helpers/checks/spamcheck.js')
, { checkRealMimeTypes, thumbSize, thumbExtension, videoThumbPercentage,
postPasswordSecret, strictFiltering, animatedGifThumbnails } = require(__dirname+'/../../configs/main.js')
postPasswordSecret, strictFiltering, animatedGifThumbnails,
audioThumbnails } = require(__dirname+'/../../configs/main.js')
, buildQueue = require(__dirname+'/../../queue.js')
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js')
, { buildThread } = require(__dirname+'/../../helpers/tasks.js');
@ -239,12 +241,11 @@ module.exports = async (req, res, next) => {
//type and subtype
const [type, subtype] = processedFile.mimetype.split('/');
if (type !== 'audio') { //audio doesnt need thumb
processedFile.thumbextension = thumbExtension;
}
let imageData;
let firstFrameOnly = true;
if (type === 'image') {
processedFile.thumbextension = thumbExtension;
///detect images with opacity for PNG thumbnails, set thumbextension before increment
try {
imageData = await imageIdentify(req.files.file[i].tempFilePath, null, true);
@ -278,6 +279,13 @@ module.exports = async (req, res, next) => {
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
@ -295,9 +303,9 @@ module.exports = async (req, res, next) => {
await moveUpload(file, processedFile.filename, 'file');
}
} else {
const existsThumb = await pathExists(`${uploadDirectory}/file/thumb-${processedFile.hash}${processedFile.thumbextension}`);
switch (type) {
case 'image': {
const existsThumb = await pathExists(`${uploadDirectory}/file/thumb-${processedFile.hash}${processedFile.thumbextension}`);
if (!existsFull) {
await moveUpload(file, processedFile.filename, 'file');
}
@ -308,7 +316,6 @@ module.exports = async (req, res, next) => {
break;
}
case 'video': {
const existsThumb = await pathExists(`${uploadDirectory}/file/thumb-${processedFile.hash}${processedFile.thumbextension}`);
//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
@ -351,10 +358,17 @@ module.exports = async (req, res, next) => {
const audioData = await ffprobe(req.files.file[i].tempFilePath, null, true);
processedFile.duration = audioData.format.duration;
processedFile.durationString = timeUtils.durationString(audioData.format.duration*1000);
processedFile.hasThumb = false;
processedFile.hasThumb = audioThumbnails;
if (!existsFull) {
await moveUpload(file, processedFile.filename, 'file');
}
if (audioThumbnails && !existsThumb) {
await audioThumbnail(processedFile);
// audio thumbnail is always thumbSize x thumbSize
processedFile.geometry = {
thumbWidth: thumbSize, thumbHeight: thumbSize,
};
}
break;
}
default:
@ -362,7 +376,7 @@ module.exports = async (req, res, next) => {
}
}
if (processedFile.hasThumb === true) {
if (processedFile.hasThumb === true && type !== 'audio') {
if (processedFile.geometry.width < thumbSize && processedFile.geometry.height < thumbSize) {
//dont scale up thumbnail for smaller images
processedFile.geometry.thumbwidth = processedFile.geometry.width;

@ -28,12 +28,12 @@ mixin catalogtile(board, post, index)
- const file = post.files[0]
if post.spoiler || file.spoiler
div.spoilerimg.catalog-thumb
else if file.hasThumb
img.catalog-thumb(src=`/file/thumb-${file.hash}${file.thumbextension}` width=file.geometry.thumbwidth height=file.geometry.thumbheight loading='lazy')
else if file.attachment
div.attachmentimg.catalog-thumb
else if file.mimetype.startsWith('audio')
div.audioimg.catalog-thumb
else if file.hasThumb
img.catalog-thumb(src=`/file/thumb-${file.hash}${file.thumbextension}` width=file.geometry.thumbwidth height=file.geometry.thumbheight loading='lazy')
else
img.catalog-thumb(src=`/file/${file.filename}` width=file.geometry.width height=file.geometry.height loading='lazy')
if post.message

@ -83,12 +83,12 @@ mixin post(post, truncate, manage=false, globalmanage=false, ban=false)
a(target='_blank' href=`/file/${file.filename}`)
if post.spoiler || file.spoiler
div.spoilerimg.file-thumb
else if file.hasThumb
img.file-thumb(src=`/file/thumb-${file.hash}${file.thumbextension}` height=file.geometry.thumbheight width=file.geometry.thumbwidth loading='lazy')
else if file.attachment
div.attachmentimg.file-thumb
else if type === 'audio'
div.audioimg.file-thumb
else if file.hasThumb
img.file-thumb(src=`/file/thumb-${file.hash}${file.thumbextension}` height=file.geometry.thumbheight width=file.geometry.thumbwidth loading='lazy')
else
img.file-thumb(src=`/file/${file.filename}` height=file.geometry.height width=file.geometry.width loading='lazy')
- if (post.message && modview) { post.message = post.message.replace(new RegExp(`<a class="quote" href="/${post.board}`, 'g'), `<a class="quote" href="/${post.board}/manage`); } //quick & dirty solution to a bigger problem/design issue

Loading…
Cancel
Save