transcoding:
enabled: false
threads: 2
+ resolutions: # Only created if the original video has a higher resolution
+ 240p: true
+ 360p: true
+ 480p: true
+ 720p: true
+ 1080p: true
retryTransactionWrapper,
generateRandomString,
getFormattedObjects,
- renamePromise
+ renamePromise,
+ getVideoFileHeight
} from '../../../helpers'
import { TagInstance, VideoInstance } from '../../../models'
-import { VideoCreate, VideoUpdate, VideoResolution } from '../../../../shared'
+import { VideoCreate, VideoUpdate } from '../../../../shared'
import { abuseVideoRouter } from './abuse'
import { blacklistRouter } from './blacklist'
return { author, tagInstances, video }
})
.then(({ author, tagInstances, video }) => {
+ const videoFilePath = join(CONFIG.STORAGE.VIDEOS_DIR, videoPhysicalFile.filename)
+ return getVideoFileHeight(videoFilePath)
+ .then(height => ({ author, tagInstances, video, videoFileHeight: height }))
+ })
+ .then(({ author, tagInstances, video, videoFileHeight }) => {
const videoFileData = {
extname: extname(videoPhysicalFile.filename),
- resolution: VideoResolution.ORIGINAL,
+ resolution: videoFileHeight,
size: videoPhysicalFile.size
}
VIDEO_CATEGORIES,
VIDEO_LICENCES,
VIDEO_LANGUAGES,
- VIDEO_RATE_TYPES,
- VIDEO_FILE_RESOLUTIONS
+ VIDEO_RATE_TYPES
} from '../../initializers'
import { isUserUsernameValid } from './users'
import { isArray, exists } from './misc'
}
function isVideoFileResolutionValid (value: string) {
- return VIDEO_FILE_RESOLUTIONS[value] !== undefined
+ return exists(value) && validator.isInt(value + '')
}
function isVideoFileExtnameValid (value: string) {
--- /dev/null
+import * as Promise from 'bluebird'
+import * as ffmpeg from 'fluent-ffmpeg'
+
+import { CONFIG } from '../initializers'
+import { VideoResolution } from '../../shared/models/videos/video-resolution.enum'
+
+function getVideoFileHeight (path: string) {
+ return new Promise<number>((res, rej) => {
+ ffmpeg.ffprobe(path, (err, metadata) => {
+ if (err) return rej(err)
+
+ const videoStream = metadata.streams.find(s => s.codec_type === 'video')
+ return res(videoStream.height)
+ })
+ })
+}
+
+function getDurationFromVideoFile (path: string) {
+ return new Promise<number>((res, rej) => {
+ ffmpeg.ffprobe(path, (err, metadata) => {
+ if (err) return rej(err)
+
+ return res(Math.floor(metadata.format.duration))
+ })
+ })
+}
+
+function generateImageFromVideoFile (fromPath: string, folder: string, imageName: string, size?: string) {
+ const options = {
+ filename: imageName,
+ count: 1,
+ folder
+ }
+
+ if (size !== undefined) {
+ options['size'] = size
+ }
+
+ return new Promise<string>((res, rej) => {
+ ffmpeg(fromPath)
+ .on('error', rej)
+ .on('end', () => res(imageName))
+ .thumbnail(options)
+ })
+}
+
+type TranscodeOptions = {
+ inputPath: string
+ outputPath: string
+ resolution?: VideoResolution
+}
+
+function transcode (options: TranscodeOptions) {
+ return new Promise<void>((res, rej) => {
+ let command = ffmpeg(options.inputPath)
+ .output(options.outputPath)
+ .videoCodec('libx264')
+ .outputOption('-threads ' + CONFIG.TRANSCODING.THREADS)
+ .outputOption('-movflags faststart')
+
+ if (options.resolution !== undefined) {
+ const size = `${options.resolution}x?` // '720x?' for example
+ command = command.size(size)
+ }
+
+ command.on('error', rej)
+ .on('end', res)
+ .run()
+ })
+}
+
+// ---------------------------------------------------------------------------
+
+export {
+ getVideoFileHeight,
+ getDurationFromVideoFile,
+ generateImageFromVideoFile,
+ transcode
+}
export * from './core-utils'
export * from './logger'
export * from './custom-validators'
+export * from './ffmpeg-utils'
export * from './database-utils'
export * from './peertube-crypto'
export * from './requests'
]
for (const resolution of resolutions) {
- if (configResolutions[resolution.toString()] === true && videoFileHeight >= resolution) {
+ if (configResolutions[resolution.toString()] === true && videoFileHeight > resolution) {
resolutionsEnabled.push(resolution)
}
}
14: 'Italian'
}
-// TODO: use VideoResolution when https://github.com/Microsoft/TypeScript/issues/13042 is fixed
-const VIDEO_FILE_RESOLUTIONS: { [ id: number ]: string } = {
- 0: 'original',
- 240: '240p',
- 360: '360p',
- 480: '480p',
- 720: '720p',
- 1080: '1080p'
-}
-
// ---------------------------------------------------------------------------
// Score a pod has when we create it as a friend
THUMBNAILS_SIZE,
USER_ROLES,
VIDEO_CATEGORIES,
- VIDEO_FILE_RESOLUTIONS,
VIDEO_LANGUAGES,
VIDEO_LICENCES,
VIDEO_RATE_TYPES
import { readdirPromise, renamePromise } from '../../helpers/core-utils'
import { CONFIG } from '../../initializers/constants'
+import { getVideoFileHeight } from '../../helpers/ffmpeg-utils'
function up (utils: {
transaction: Sequelize.Transaction,
const torrentDir = CONFIG.STORAGE.TORRENTS_DIR
const videoFileDir = CONFIG.STORAGE.VIDEOS_DIR
- return readdirPromise(torrentDir)
- .then(torrentFiles => {
- const tasks: Promise<any>[] = []
- for (const torrentFile of torrentFiles) {
- const matches = /^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.torrent/.exec(torrentFile)
- if (matches === null) {
- console.log('Invalid torrent file name %s.', torrentFile)
- continue
- }
-
- const newTorrentName = matches[1] + '-original.torrent'
- const p = renamePromise(join(torrentDir, torrentFile), join(torrentDir, newTorrentName))
- tasks.push(p)
- }
-
- return Promise.all(tasks)
- })
- .then(() => {
- return readdirPromise(videoFileDir)
- })
+ return readdirPromise(videoFileDir)
.then(videoFiles => {
const tasks: Promise<any>[] = []
for (const videoFile of videoFiles) {
continue
}
- const newVideoFileName = matches[1] + '-original.' + matches[2]
- const p = renamePromise(join(videoFileDir, videoFile), join(videoFileDir, newVideoFileName))
+ const uuid = matches[1]
+ const ext = matches[2]
+
+ const p = getVideoFileHeight(join(videoFileDir, videoFile))
+ .then(height => {
+ const oldTorrentName = uuid + '.torrent'
+ const newTorrentName = uuid + '-' + height + '.torrent'
+ return renamePromise(join(torrentDir, oldTorrentName), join(torrentDir, newTorrentName)).then(() => height)
+ })
+ .then(height => {
+ const newVideoFileName = uuid + '-' + height + '.' + ext
+ return renamePromise(join(videoFileDir, videoFile), join(videoFileDir, newVideoFileName)).then(() => height)
+ })
+ .then(height => {
+ const query = 'UPDATE "VideoFiles" SET "resolution" = ' + height +
+ ' WHERE "videoId" = (SELECT "id" FROM "Videos" WHERE "uuid" = \'' + uuid + '\')'
+ return utils.sequelize.query(query)
+ })
+
tasks.push(p)
}
isVideoNSFWValid,
isVideoIdOrUUIDValid,
isVideoAbuseReasonValid,
- isVideoRatingTypeValid
+ isVideoRatingTypeValid,
+ getDurationFromVideoFile
} from '../../helpers'
import { VideoInstance } from '../../models'
return undefined
}
- return db.Video.getDurationFromFile(videoFile.path)
+ return getDurationFromVideoFile(videoFile.path)
.catch(err => {
logger.error('Invalid input file in videosAddValidator.', err)
res.status(400)
isUserDisplayNSFWValid,
isUserVideoQuotaValid
} from '../../helpers'
-import { VideoResolution } from '../../../shared'
import { addMethodsToModel } from '../utils'
import {
// ---------------------------------------------------------------------------
function getOriginalVideoFileTotalFromUser (user: UserInstance) {
- // attributes = [] because we don't want other fields than the sum
- const query = {
- where: {
- resolution: VideoResolution.ORIGINAL
- },
- include: [
- {
- attributes: [],
- model: User['sequelize'].models.Video,
- include: [
- {
- attributes: [],
- model: User['sequelize'].models.Author,
- include: [
- {
- attributes: [],
- model: User['sequelize'].models.User,
- where: {
- id: user.id
- }
- }
- ]
- }
- ]
- }
- ]
+ // Don't use sequelize because we need to use a subquery
+ const query = 'SELECT SUM("size") AS "total" FROM ' +
+ '(SELECT MAX("VideoFiles"."size") AS "size" FROM "VideoFiles" ' +
+ 'INNER JOIN "Videos" ON "VideoFiles"."videoId" = "Videos"."id" ' +
+ 'INNER JOIN "Authors" ON "Videos"."authorId" = "Authors"."id" ' +
+ 'INNER JOIN "Users" ON "Authors"."userId" = "Users"."id" ' +
+ 'WHERE "Users"."id" = $userId GROUP BY "Videos"."id") t'
+
+ const options = {
+ bind: { userId: user.id },
+ type: Sequelize.QueryTypes.SELECT
}
+ return User['sequelize'].query(query, options).then(([ { total } ]) => {
+ if (total === null) return 0
- return User['sequelize'].models.VideoFile.sum('size', query)
+ return parseInt(total, 10)
+ })
}
// Return thumbnail name
export type GenerateThumbnailFromData = (video: VideoInstance, thumbnailData: string) => Promise<string>
- export type GetDurationFromFile = (videoPath: string) => Promise<number>
export type List = () => Promise<VideoInstance[]>
export type ListOwnedAndPopulateAuthorAndTags = () => Promise<VideoInstance[]>
export interface VideoClass {
generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
- getDurationFromFile: VideoMethods.GetDurationFromFile
list: VideoMethods.List
listForApi: VideoMethods.ListForApi
listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
import * as safeBuffer from 'safe-buffer'
const Buffer = safeBuffer.Buffer
-import * as ffmpeg from 'fluent-ffmpeg'
import * as magnetUtil from 'magnet-uri'
import { map } from 'lodash'
import * as parseTorrent from 'parse-torrent'
import { join } from 'path'
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
+import { maxBy } from 'lodash'
import { TagInstance } from './tag-interface'
import {
renamePromise,
writeFilePromise,
createTorrentPromise,
- statPromise
+ statPromise,
+ generateImageFromVideoFile,
+ transcode,
+ getVideoFileHeight
} from '../../helpers'
import {
CONFIG,
VIDEO_CATEGORIES,
VIDEO_LICENCES,
VIDEO_LANGUAGES,
- THUMBNAILS_SIZE,
- VIDEO_FILE_RESOLUTIONS
+ THUMBNAILS_SIZE
} from '../../initializers'
import { removeVideoToFriends } from '../../lib'
import { VideoResolution } from '../../../shared'
let getOriginalFileHeight: VideoMethods.GetOriginalFileHeight
let generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
-let getDurationFromFile: VideoMethods.GetDurationFromFile
let list: VideoMethods.List
let listForApi: VideoMethods.ListForApi
let loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
associate,
generateThumbnailFromData,
- getDurationFromFile,
list,
listForApi,
listOwnedAndPopulateAuthorAndTags,
getOriginalFile = function (this: VideoInstance) {
if (Array.isArray(this.VideoFiles) === false) return undefined
- return this.VideoFiles.find(file => file.resolution === VideoResolution.ORIGINAL)
+ // The original file is the file that have the higher resolution
+ return maxBy(this.VideoFiles, file => file.resolution)
}
getVideoFilename = function (this: VideoInstance, videoFile: VideoFileInstance) {
- return this.uuid + '-' + VIDEO_FILE_RESOLUTIONS[videoFile.resolution] + videoFile.extname
+ return this.uuid + '-' + videoFile.resolution + videoFile.extname
}
getThumbnailName = function (this: VideoInstance) {
getTorrentFileName = function (this: VideoInstance, videoFile: VideoFileInstance) {
const extension = '.torrent'
- return this.uuid + '-' + VIDEO_FILE_RESOLUTIONS[videoFile.resolution] + extension
+ return this.uuid + '-' + videoFile.resolution + extension
}
isOwned = function (this: VideoInstance) {
}
createPreview = function (this: VideoInstance, videoFile: VideoFileInstance) {
- return generateImage(this, this.getVideoFilePath(videoFile), CONFIG.STORAGE.PREVIEWS_DIR, this.getPreviewName(), null)
+ return generateImageFromVideoFile(
+ this.getVideoFilePath(videoFile),
+ CONFIG.STORAGE.PREVIEWS_DIR,
+ this.getPreviewName()
+ )
}
createThumbnail = function (this: VideoInstance, videoFile: VideoFileInstance) {
- return generateImage(this, this.getVideoFilePath(videoFile), CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName(), THUMBNAILS_SIZE)
+ return generateImageFromVideoFile(
+ this.getVideoFilePath(videoFile),
+ CONFIG.STORAGE.THUMBNAILS_DIR,
+ this.getThumbnailName(),
+ THUMBNAILS_SIZE
+ )
}
getVideoFilePath = function (this: VideoInstance, videoFile: VideoFileInstance) {
// Format and sort video files
json.files = this.VideoFiles
.map(videoFile => {
- let resolutionLabel = VIDEO_FILE_RESOLUTIONS[videoFile.resolution]
- if (!resolutionLabel) resolutionLabel = 'Unknown'
+ let resolutionLabel = videoFile.resolution + 'p'
const videoFileJson = {
resolution: videoFile.resolution,
const videoInputPath = join(videosDirectory, this.getVideoFilename(inputVideoFile))
const videoOutputPath = join(videosDirectory, this.id + '-transcoded' + newExtname)
- return new Promise<void>((res, rej) => {
- ffmpeg(videoInputPath)
- .output(videoOutputPath)
- .videoCodec('libx264')
- .outputOption('-threads ' + CONFIG.TRANSCODING.THREADS)
- .outputOption('-movflags faststart')
- .on('error', rej)
- .on('end', () => {
-
- return unlinkPromise(videoInputPath)
- .then(() => {
- // Important to do this before getVideoFilename() to take in account the new file extension
- inputVideoFile.set('extname', newExtname)
-
- return renamePromise(videoOutputPath, this.getVideoFilePath(inputVideoFile))
- })
- .then(() => {
- return statPromise(this.getVideoFilePath(inputVideoFile))
- })
- .then(stats => {
- return inputVideoFile.set('size', stats.size)
- })
- .then(() => {
- return this.createTorrentAndSetInfoHash(inputVideoFile)
- })
- .then(() => {
- return inputVideoFile.save()
- })
- .then(() => {
- return res()
- })
- .catch(err => {
- // Auto destruction...
- this.destroy().catch(err => logger.error('Cannot destruct video after transcoding failure.', err))
-
- return rej(err)
- })
- })
- .run()
- })
+ const transcodeOptions = {
+ inputPath: videoInputPath,
+ outputPath: videoOutputPath
+ }
+
+ return transcode(transcodeOptions)
+ .then(() => {
+ return unlinkPromise(videoInputPath)
+ })
+ .then(() => {
+ // Important to do this before getVideoFilename() to take in account the new file extension
+ inputVideoFile.set('extname', newExtname)
+
+ return renamePromise(videoOutputPath, this.getVideoFilePath(inputVideoFile))
+ })
+ .then(() => {
+ return statPromise(this.getVideoFilePath(inputVideoFile))
+ })
+ .then(stats => {
+ return inputVideoFile.set('size', stats.size)
+ })
+ .then(() => {
+ return this.createTorrentAndSetInfoHash(inputVideoFile)
+ })
+ .then(() => {
+ return inputVideoFile.save()
+ })
+ .then(() => {
+ return undefined
+ })
+ .catch(err => {
+ // Auto destruction...
+ this.destroy().catch(err => logger.error('Cannot destruct video after transcoding failure.', err))
+
+ throw err
+ })
}
transcodeOriginalVideofile = function (this: VideoInstance, resolution: VideoResolution) {
videoId: this.id
})
const videoOutputPath = join(videosDirectory, this.getVideoFilename(newVideoFile))
- const resolutionOption = `${resolution}x?` // '720x?' for example
-
- return new Promise<void>((res, rej) => {
- ffmpeg(videoInputPath)
- .output(videoOutputPath)
- .videoCodec('libx264')
- .size(resolutionOption)
- .outputOption('-threads ' + CONFIG.TRANSCODING.THREADS)
- .outputOption('-movflags faststart')
- .on('error', rej)
- .on('end', () => {
- return statPromise(videoOutputPath)
- .then(stats => {
- newVideoFile.set('size', stats.size)
-
- return undefined
- })
- .then(() => {
- return this.createTorrentAndSetInfoHash(newVideoFile)
- })
- .then(() => {
- return newVideoFile.save()
- })
- .then(() => {
- return this.VideoFiles.push(newVideoFile)
- })
- .then(() => {
- return res()
- })
- .catch(rej)
- })
- .run()
- })
+
+ const transcodeOptions = {
+ inputPath: videoInputPath,
+ outputPath: videoOutputPath,
+ resolution
+ }
+ return transcode(transcodeOptions)
+ .then(() => {
+ return statPromise(videoOutputPath)
+ })
+ .then(stats => {
+ newVideoFile.set('size', stats.size)
+
+ return undefined
+ })
+ .then(() => {
+ return this.createTorrentAndSetInfoHash(newVideoFile)
+ })
+ .then(() => {
+ return newVideoFile.save()
+ })
+ .then(() => {
+ return this.VideoFiles.push(newVideoFile)
+ })
+ .then(() => undefined)
}
getOriginalFileHeight = function (this: VideoInstance) {
const originalFilePath = this.getVideoFilePath(this.getOriginalFile())
- return new Promise<number>((res, rej) => {
- ffmpeg.ffprobe(originalFilePath, (err, metadata) => {
- if (err) return rej(err)
-
- const videoStream = metadata.streams.find(s => s.codec_type === 'video')
- return res(videoStream.height)
- })
- })
+ return getVideoFileHeight(originalFilePath)
}
removeThumbnail = function (this: VideoInstance) {
})
}
-getDurationFromFile = function (videoPath: string) {
- return new Promise<number>((res, rej) => {
- ffmpeg.ffprobe(videoPath, (err, metadata) => {
- if (err) return rej(err)
-
- return res(Math.floor(metadata.format.duration))
- })
- })
-}
-
list = function () {
const query = {
include: [ Video['sequelize'].models.VideoFile ]
}
}
}
-
-function generateImage (video: VideoInstance, videoPath: string, folder: string, imageName: string, size: string) {
- const options = {
- filename: imageName,
- count: 1,
- folder
- }
-
- if (size) {
- options['size'] = size
- }
-
- return new Promise<string>((res, rej) => {
- ffmpeg(videoPath)
- .on('error', rej)
- .on('end', () => res(imageName))
- .thumbnail(options)
- })
-}
const file = video.files[0]
const magnetUri = file.magnetUri
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.resolution).to.equal(0)
- expect(file.resolutionLabel).to.equal('original')
+ expect(file.resolution).to.equal(720)
+ expect(file.resolutionLabel).to.equal('720p')
expect(file.size).to.equal(572456)
if (server.url !== 'http://localhost:9001') {
expect(dateIsValid(video.updatedAt)).to.be.true
expect(video.author).to.equal('root')
- expect(video.files).to.have.lengthOf(5)
+ expect(video.files).to.have.lengthOf(4)
// Check common attributes
for (const file of video.files) {
}
}
- const originalFile = video.files.find(f => f.resolution === 0)
- expect(originalFile).not.to.be.undefined
- expect(originalFile.resolutionLabel).to.equal('original')
- expect(originalFile.size).to.be.above(700000).and.below(720000)
-
const file240p = video.files.find(f => f.resolution === 240)
expect(file240p).not.to.be.undefined
expect(file240p.resolutionLabel).to.equal('240p')
const file720p = video.files.find(f => f.resolution === 720)
expect(file720p).not.to.be.undefined
expect(file720p.resolutionLabel).to.equal('720p')
- expect(file720p.size).to.be.above(310000).and.below(320000)
+ expect(file720p.size).to.be.above(700000).and.below(7200000)
const test = await testVideoImage(server.url, 'video_short2.webm', video.thumbnailPath)
expect(test).to.equal(true)
const file1 = video1.files[0]
expect(file1.magnetUri).to.have.lengthOf.above(2)
- expect(file1.resolution).to.equal(0)
- expect(file1.resolutionLabel).to.equal('original')
+ expect(file1.resolution).to.equal(720)
+ expect(file1.resolutionLabel).to.equal('720p')
expect(file1.size).to.equal(292677)
expect(video2.name).to.equal('my super name for pod 3-2')
const file2 = video2.files[0]
const magnetUri2 = file2.magnetUri
expect(file2.magnetUri).to.have.lengthOf.above(2)
- expect(file2.resolution).to.equal(0)
- expect(file2.resolutionLabel).to.equal('original')
+ expect(file2.resolution).to.equal(720)
+ expect(file2.resolutionLabel).to.equal('720p')
expect(file2.size).to.equal(218910)
if (server.url !== 'http://localhost:9003') {
expect(torrent.files.length).to.equal(1)
expect(torrent.files[0].path).to.exist.and.to.not.equal('')
})
+
+ it('Should add the file 2 in 360p by asking pod 1', async function () {
+ // Yes, this could be long
+ this.timeout(200000)
+
+ const res = await getVideosList(servers[0].url)
+
+ const video = res.body.data.find(v => v.name === 'my super name for pod 2')
+ const file = video.files.find(f => f.resolution === 360)
+ expect(file).not.to.be.undefined
+
+ const torrent = await webtorrentAdd(file.magnetUri)
+ expect(torrent.files).to.be.an('array')
+ expect(torrent.files.length).to.equal(1)
+ expect(torrent.files[0].path).to.exist.and.to.not.equal('')
+ })
})
describe('Should update video views, likes and dislikes', function () {
const file = videoUpdated.files[0]
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.resolution).to.equal(0)
- expect(file.resolutionLabel).to.equal('original')
+ expect(file.resolution).to.equal(720)
+ expect(file.resolutionLabel).to.equal('720p')
expect(file.size).to.equal(292677)
const test = await testVideoImage(server.url, 'video_short3.webm', videoUpdated.thumbnailPath)
const file = video.files[0]
const magnetUri = file.magnetUri
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.resolution).to.equal(0)
- expect(file.resolutionLabel).to.equal('original')
+ expect(file.resolution).to.equal(720)
+ expect(file.resolutionLabel).to.equal('720p')
expect(file.size).to.equal(218910)
const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath)
const file = video.files[0]
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.resolution).to.equal(0)
- expect(file.resolutionLabel).to.equal('original')
+ expect(file.resolution).to.equal(720)
+ expect(file.resolutionLabel).to.equal('720p')
expect(file.size).to.equal(218910)
const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath)
const file = video.files[0]
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.resolution).to.equal(0)
- expect(file.resolutionLabel).to.equal('original')
+ expect(file.resolution).to.equal(720)
+ expect(file.resolutionLabel).to.equal('720p')
expect(file.size).to.equal(218910)
const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath)
const file = video.files[0]
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.resolution).to.equal(0)
- expect(file.resolutionLabel).to.equal('original')
+ expect(file.resolution).to.equal(720)
+ expect(file.resolutionLabel).to.equal('720p')
expect(file.size).to.equal(218910)
const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath)
const file = video.files[0]
const magnetUri = file.magnetUri
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.resolution).to.equal(0)
- expect(file.resolutionLabel).to.equal('original')
+ expect(file.resolution).to.equal(720)
+ expect(file.resolutionLabel).to.equal('720p')
expect(file.size).to.equal(292677)
const test = await testVideoImage(server.url, 'video_short3.webm', video.thumbnailPath)
const file = video.files[0]
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.resolution).to.equal(0)
- expect(file.resolutionLabel).to.equal('original')
+ expect(file.resolution).to.equal(720)
+ expect(file.resolutionLabel).to.equal('720p')
expect(file.size).to.equal(292677)
})
const file = video.files[0]
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.resolution).to.equal(0)
- expect(file.resolutionLabel).to.equal('original')
+ expect(file.resolution).to.equal(720)
+ expect(file.resolutionLabel).to.equal('720p')
expect(file.size).to.equal(292677)
})
const res = await getVideosList(servers[1].url)
const video = res.body.data[0]
- expect(video.files).to.have.lengthOf(5)
+ expect(video.files).to.have.lengthOf(4)
const magnetUri = video.files[0].magnetUri
expect(magnetUri).to.match(/\.mp4/)
expect(videos).to.have.lengthOf(2)
for (const video of videos) {
- expect(video.files).to.have.lengthOf(5)
+ expect(video.files).to.have.lengthOf(4)
for (const file of video.files) {
expect(file.magnetUri).to.contain('localhost%3A9002%2Ftracker%2Fsocket')
expect(file.magnetUri).to.contain('localhost%3A9002%2Fstatic%2Fwebseed%2F')
- const torrent = await parseTorrentVideo(server, video.uuid, file.resolutionLabel)
+ const torrent = await parseTorrentVideo(server, video.uuid, file.resolution)
expect(torrent.announce[0]).to.equal('ws://localhost:9002/tracker/socket')
expect(torrent.urlList[0]).to.contain('http://localhost:9002/static/webseed')
}
req.field('tags[' + i + ']', attributes.tags[i])
}
- let filepath = ''
+ let filePath = ''
if (isAbsolute(attributes.fixture)) {
- filepath = attributes.fixture
+ filePath = attributes.fixture
} else {
- filepath = join(__dirname, '..', 'api', 'fixtures', attributes.fixture)
+ filePath = join(__dirname, '..', 'api', 'fixtures', attributes.fixture)
}
- return req.attach('videofile', filepath)
+ return req.attach('videofile', filePath)
.expect(specialStatus)
}
.expect(specialStatus)
}
-function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolutionLabel: string) {
+function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
return new Promise<any>((res, rej) => {
- const torrentName = videoUUID + '-' + resolutionLabel + '.torrent'
+ const torrentName = videoUUID + '-' + resolution + '.torrent'
const torrentPath = join(__dirname, '..', '..', '..', 'test' + server.serverNumber, 'torrents', torrentName)
readFile(torrentPath, (err, data) => {
if (err) return rej(err)
export enum VideoResolution {
- ORIGINAL = 0,
H_240P = 240,
H_360P = 360,
H_480P = 480,