mirror of https://github.com/Chocobozzz/PeerTube
Server: add video preview
parent
830bcd0f82
commit
6a94a109b4
|
@ -8,6 +8,7 @@
|
||||||
/uploads/
|
/uploads/
|
||||||
/videos/
|
/videos/
|
||||||
/thumbnails/
|
/thumbnails/
|
||||||
|
/previews/
|
||||||
/certs/
|
/certs/
|
||||||
/logs/
|
/logs/
|
||||||
/torrents/
|
/torrents/
|
||||||
|
|
|
@ -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/'
|
||||||
|
|
|
@ -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'))
|
||||||
|
|
|
@ -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 = []
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue