Server: add video preview

pull/24/head
Chocobozzz 2016-11-11 11:52:24 +01:00
parent 830bcd0f82
commit 6a94a109b4
6 changed files with 39 additions and 3 deletions

1
.gitignore vendored
View File

@ -8,6 +8,7 @@
/uploads/ /uploads/
/videos/ /videos/
/thumbnails/ /thumbnails/
/previews/
/certs/ /certs/
/logs/ /logs/
/torrents/ /torrents/

View File

@ -16,5 +16,6 @@ storage:
certs: 'certs/' certs: 'certs/'
videos: 'videos/' videos: 'videos/'
logs: 'logs/' logs: 'logs/'
previews: 'previews/'
thumbnails: 'thumbnails/' thumbnails: 'thumbnails/'
torrents: 'torrents/' torrents: 'torrents/'

View File

@ -71,7 +71,8 @@ const apiRoute = '/api/' + constants.API_VERSION
app.use(apiRoute, routes.api) app.use(apiRoute, routes.api)
app.use('/', routes.client) app.use('/', routes.client)
// Static files // Static client files
// TODO: move in client
app.use('/client', express.static(path.join(__dirname, '/client/dist'), { maxAge: constants.STATIC_MAX_AGE })) app.use('/client', express.static(path.join(__dirname, '/client/dist'), { maxAge: constants.STATIC_MAX_AGE }))
// 404 for static files not found // 404 for static files not found
app.use('/client/*', function (req, res, next) { app.use('/client/*', function (req, res, next) {
@ -89,6 +90,10 @@ app.use(constants.STATIC_PATHS.WEBSEED, cors(), express.static(videosPhysicalPat
const thumbnailsPhysicalPath = constants.CONFIG.STORAGE.THUMBNAILS_DIR const thumbnailsPhysicalPath = constants.CONFIG.STORAGE.THUMBNAILS_DIR
app.use(constants.STATIC_PATHS.THUMBNAILS, express.static(thumbnailsPhysicalPath, { maxAge: constants.STATIC_MAX_AGE })) app.use(constants.STATIC_PATHS.THUMBNAILS, express.static(thumbnailsPhysicalPath, { maxAge: constants.STATIC_MAX_AGE }))
// Video previews path for express
const previewsPhysicalPath = constants.CONFIG.STORAGE.PREVIEWS_DIR
app.use(constants.STATIC_PATHS.PREVIEWS, express.static(previewsPhysicalPath, { maxAge: constants.STATIC_MAX_AGE }))
// Always serve index client page // Always serve index client page
app.use('/*', function (req, res, next) { app.use('/*', function (req, res, next) {
res.sendFile(path.join(__dirname, './client/dist/index.html')) res.sendFile(path.join(__dirname, './client/dist/index.html'))

View File

@ -30,7 +30,7 @@ function checkMissedConfig () {
const required = [ 'listen.port', const required = [ 'listen.port',
'webserver.https', 'webserver.hostname', 'webserver.port', 'webserver.https', 'webserver.hostname', 'webserver.port',
'database.hostname', 'database.port', 'database.suffix', 'database.hostname', 'database.port', 'database.suffix',
'storage.certs', 'storage.videos', 'storage.logs', 'storage.thumbnails' 'storage.certs', 'storage.videos', 'storage.logs', 'storage.thumbnails', 'storage.previews'
] ]
const miss = [] const miss = []

View File

@ -44,6 +44,7 @@ const CONFIG = {
LOG_DIR: path.join(__dirname, '..', '..', config.get('storage.logs')), LOG_DIR: path.join(__dirname, '..', '..', config.get('storage.logs')),
VIDEOS_DIR: path.join(__dirname, '..', '..', config.get('storage.videos')), VIDEOS_DIR: path.join(__dirname, '..', '..', config.get('storage.videos')),
THUMBNAILS_DIR: path.join(__dirname, '..', '..', config.get('storage.thumbnails')), THUMBNAILS_DIR: path.join(__dirname, '..', '..', config.get('storage.thumbnails')),
PREVIEWS_DIR: path.join(__dirname, '..', '..', config.get('storage.previews')),
TORRENTS_DIR: path.join(__dirname, '..', '..', config.get('storage.torrents')) TORRENTS_DIR: path.join(__dirname, '..', '..', config.get('storage.torrents'))
}, },
WEBSERVER: { WEBSERVER: {
@ -135,6 +136,7 @@ const BCRYPT_SALT_SIZE = 10
// Express static paths (router) // Express static paths (router)
const STATIC_PATHS = { const STATIC_PATHS = {
PREVIEWS: '/static/previews',
THUMBNAILS: '/static/thumbnails', THUMBNAILS: '/static/thumbnails',
TORRENTS: '/static/torrents/', TORRENTS: '/static/torrents/',
WEBSEED: '/static/webseed/' WEBSEED: '/static/webseed/'
@ -145,6 +147,7 @@ let STATIC_MAX_AGE = '30d'
// Videos thumbnail size // Videos thumbnail size
const THUMBNAILS_SIZE = '200x110' const THUMBNAILS_SIZE = '200x110'
const PREVIEWS_SIZE = '640x480'
const USER_ROLES = { const USER_ROLES = {
ADMIN: 'admin', ADMIN: 'admin',
@ -179,6 +182,7 @@ module.exports = {
REQUESTS_INTERVAL, REQUESTS_INTERVAL,
REQUESTS_LIMIT, REQUESTS_LIMIT,
RETRY_REQUESTS, RETRY_REQUESTS,
PREVIEWS_SIZE,
SEARCHABLE_COLUMNS, SEARCHABLE_COLUMNS,
SORTABLE_COLUMNS, SORTABLE_COLUMNS,
STATIC_MAX_AGE, STATIC_MAX_AGE,

View File

@ -82,6 +82,9 @@ VideoSchema.pre('remove', function (next) {
}, },
function (callback) { function (callback) {
removeTorrent(video, callback) removeTorrent(video, callback)
},
function (callback) {
removePreview(video, callback)
} }
) )
} }
@ -125,6 +128,9 @@ VideoSchema.pre('save', function (next) {
}, },
function (callback) { function (callback) {
createThumbnail(videoPath, callback) createThumbnail(videoPath, callback)
},
function (callback) {
createPreview(videoPath, callback)
} }
) )
@ -261,11 +267,30 @@ function removeFile (video, callback) {
fs.unlink(constants.CONFIG.STORAGE.VIDEOS_DIR + video.filename, callback) fs.unlink(constants.CONFIG.STORAGE.VIDEOS_DIR + video.filename, callback)
} }
// Maybe the torrent is not seeded, but we catch the error to don't stop the removing process
function removeTorrent (video, callback) { function removeTorrent (video, callback) {
fs.unlink(constants.CONFIG.STORAGE.TORRENTS_DIR + video.filename + '.torrent', callback) fs.unlink(constants.CONFIG.STORAGE.TORRENTS_DIR + video.filename + '.torrent', callback)
} }
function removePreview (video, callback) {
// Same name than video thumnail
// TODO: refractoring
fs.unlink(constants.CONFIG.STORAGE.PREVIEWS_DIR + video.thumbnail, callback)
}
function createPreview (videoPath, callback) {
const filename = pathUtils.basename(videoPath) + '.jpg'
ffmpeg(videoPath)
.on('error', callback)
.on('end', function () {
callback(null, filename)
})
.thumbnail({
count: 1,
folder: constants.CONFIG.STORAGE.PREVIEWS_DIR,
filename: filename
})
}
function createThumbnail (videoPath, callback) { function createThumbnail (videoPath, callback) {
const filename = pathUtils.basename(videoPath) + '.jpg' const filename = pathUtils.basename(videoPath) + '.jpg'
ffmpeg(videoPath) ffmpeg(videoPath)