Server: add video preview
This commit is contained in:
		
							parent
							
								
									830bcd0f82
								
							
						
					
					
						commit
						6a94a109b4
					
				
					 6 changed files with 39 additions and 3 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
/uploads/
 | 
			
		||||
/videos/
 | 
			
		||||
/thumbnails/
 | 
			
		||||
/previews/
 | 
			
		||||
/certs/
 | 
			
		||||
/logs/
 | 
			
		||||
/torrents/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,5 +16,6 @@ storage:
 | 
			
		|||
  certs: 'certs/'
 | 
			
		||||
  videos: 'videos/'
 | 
			
		||||
  logs: 'logs/'
 | 
			
		||||
  previews: 'previews/'
 | 
			
		||||
  thumbnails: 'thumbnails/'
 | 
			
		||||
  torrents: 'torrents/'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,7 +71,8 @@ const apiRoute = '/api/' + constants.API_VERSION
 | 
			
		|||
app.use(apiRoute, routes.api)
 | 
			
		||||
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 }))
 | 
			
		||||
// 404 for static files not found
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
app.use('/*', function (req, res, next) {
 | 
			
		||||
  res.sendFile(path.join(__dirname, './client/dist/index.html'))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ function checkMissedConfig () {
 | 
			
		|||
  const required = [ 'listen.port',
 | 
			
		||||
    'webserver.https', 'webserver.hostname', 'webserver.port',
 | 
			
		||||
    '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 = []
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,7 @@ const CONFIG = {
 | 
			
		|||
    LOG_DIR: path.join(__dirname, '..', '..', config.get('storage.logs')),
 | 
			
		||||
    VIDEOS_DIR: path.join(__dirname, '..', '..', config.get('storage.videos')),
 | 
			
		||||
    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'))
 | 
			
		||||
  },
 | 
			
		||||
  WEBSERVER: {
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +136,7 @@ const BCRYPT_SALT_SIZE = 10
 | 
			
		|||
 | 
			
		||||
// Express static paths (router)
 | 
			
		||||
const STATIC_PATHS = {
 | 
			
		||||
  PREVIEWS: '/static/previews',
 | 
			
		||||
  THUMBNAILS: '/static/thumbnails',
 | 
			
		||||
  TORRENTS: '/static/torrents/',
 | 
			
		||||
  WEBSEED: '/static/webseed/'
 | 
			
		||||
| 
						 | 
				
			
			@ -145,6 +147,7 @@ let STATIC_MAX_AGE = '30d'
 | 
			
		|||
 | 
			
		||||
// Videos thumbnail size
 | 
			
		||||
const THUMBNAILS_SIZE = '200x110'
 | 
			
		||||
const PREVIEWS_SIZE = '640x480'
 | 
			
		||||
 | 
			
		||||
const USER_ROLES = {
 | 
			
		||||
  ADMIN: 'admin',
 | 
			
		||||
| 
						 | 
				
			
			@ -179,6 +182,7 @@ module.exports = {
 | 
			
		|||
  REQUESTS_INTERVAL,
 | 
			
		||||
  REQUESTS_LIMIT,
 | 
			
		||||
  RETRY_REQUESTS,
 | 
			
		||||
  PREVIEWS_SIZE,
 | 
			
		||||
  SEARCHABLE_COLUMNS,
 | 
			
		||||
  SORTABLE_COLUMNS,
 | 
			
		||||
  STATIC_MAX_AGE,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,6 +82,9 @@ VideoSchema.pre('remove', function (next) {
 | 
			
		|||
      },
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        removeTorrent(video, callback)
 | 
			
		||||
      },
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        removePreview(video, callback)
 | 
			
		||||
      }
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -125,6 +128,9 @@ VideoSchema.pre('save', function (next) {
 | 
			
		|||
      },
 | 
			
		||||
      function (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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Maybe the torrent is not seeded, but we catch the error to don't stop the removing process
 | 
			
		||||
function removeTorrent (video, 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) {
 | 
			
		||||
  const filename = pathUtils.basename(videoPath) + '.jpg'
 | 
			
		||||
  ffmpeg(videoPath)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue