Add script to generate storyboards
This commit is contained in:
parent
d8f39b126d
commit
9c5cc50133
|
@ -49,6 +49,7 @@
|
|||
"regenerate-thumbnails": "node ./dist/scripts/regenerate-thumbnails.js",
|
||||
"create-import-video-file-job": "node ./dist/scripts/create-import-video-file-job.js",
|
||||
"create-move-video-storage-job": "node ./dist/scripts/create-move-video-storage-job.js",
|
||||
"create-generate-storyboard-job": "node ./dist/scripts/create-generate-storyboard-job.js",
|
||||
"test": "bash ./scripts/test.sh",
|
||||
"generate-cli-doc": "bash ./scripts/generate-cli-doc.sh",
|
||||
"generate-types-package": "ts-node ./packages/types/generate-package.ts",
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
import { program } from 'commander'
|
||||
import { toCompleteUUID } from '@server/helpers/custom-validators/misc'
|
||||
import { initDatabaseModels } from '@server/initializers/database'
|
||||
import { JobQueue } from '@server/lib/job-queue'
|
||||
import { VideoModel } from '@server/models/video/video'
|
||||
import { StoryboardModel } from '@server/models/video/storyboard'
|
||||
|
||||
program
|
||||
.description('Generate videos storyboard')
|
||||
.option('-v, --video [videoUUID]', 'Generate the storyboard of a specific video')
|
||||
.option('-a, --all-videos', 'Generate missing storyboards of local videos')
|
||||
.parse(process.argv)
|
||||
|
||||
const options = program.opts()
|
||||
|
||||
if (!options['video'] && !options['allVideos']) {
|
||||
console.error('You need to choose videos for storyboard generation.')
|
||||
process.exit(-1)
|
||||
}
|
||||
|
||||
run()
|
||||
.then(() => process.exit(0))
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
process.exit(-1)
|
||||
})
|
||||
|
||||
async function run () {
|
||||
await initDatabaseModels(true)
|
||||
|
||||
JobQueue.Instance.init()
|
||||
|
||||
let ids: number[] = []
|
||||
|
||||
if (options['video']) {
|
||||
const video = await VideoModel.load(toCompleteUUID(options['video']))
|
||||
|
||||
if (!video) {
|
||||
console.error('Unknown video ' + options['video'])
|
||||
process.exit(-1)
|
||||
}
|
||||
|
||||
if (video.remote === true) {
|
||||
console.error('Cannot process a remote video')
|
||||
process.exit(-1)
|
||||
}
|
||||
|
||||
if (video.isLive) {
|
||||
console.error('Cannot process live video')
|
||||
process.exit(-1)
|
||||
}
|
||||
|
||||
ids.push(video.id)
|
||||
} else {
|
||||
ids = await listLocalMissingStoryboards()
|
||||
}
|
||||
|
||||
for (const id of ids) {
|
||||
const videoFull = await VideoModel.load(id)
|
||||
|
||||
if (videoFull.isLive) continue
|
||||
|
||||
await JobQueue.Instance.createJob({
|
||||
type: 'generate-video-storyboard',
|
||||
payload: {
|
||||
videoUUID: videoFull.uuid,
|
||||
federate: true
|
||||
}
|
||||
})
|
||||
|
||||
console.log(`Created generate-storyboard job for ${videoFull.name}.`)
|
||||
}
|
||||
}
|
||||
|
||||
async function listLocalMissingStoryboards () {
|
||||
const ids = await VideoModel.listLocalIds()
|
||||
const results: number[] = []
|
||||
|
||||
for (const id of ids) {
|
||||
const storyboard = await StoryboardModel.loadByVideo(id)
|
||||
if (!storyboard) results.push(id)
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import { program } from 'commander'
|
||||
import { toCompleteUUID } from '@server/helpers/custom-validators/misc'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
import { initDatabaseModels } from '@server/initializers/database'
|
||||
import { JobQueue } from '@server/lib/job-queue'
|
||||
|
@ -32,7 +33,10 @@ if (options['toObjectStorage'] && !CONFIG.OBJECT_STORAGE.ENABLED) {
|
|||
|
||||
run()
|
||||
.then(() => process.exit(0))
|
||||
.catch(err => console.error(err))
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
process.exit(-1)
|
||||
})
|
||||
|
||||
async function run () {
|
||||
await initDatabaseModels(true)
|
||||
|
@ -42,7 +46,7 @@ async function run () {
|
|||
let ids: number[] = []
|
||||
|
||||
if (options['video']) {
|
||||
const video = await VideoModel.load(options['video'])
|
||||
const video = await VideoModel.load(toCompleteUUID(options['video']))
|
||||
|
||||
if (!video) {
|
||||
console.error('Unknown video ' + options['video'])
|
||||
|
|
|
@ -43,6 +43,11 @@ async function processGenerateStoryboard (job: Job): Promise<void> {
|
|||
const destination = join(CONFIG.STORAGE.STORYBOARDS_DIR, filename)
|
||||
|
||||
const totalSprites = buildTotalSprites(video)
|
||||
if (totalSprites === 0) {
|
||||
logger.info('Do not generate a storyboard of %s because the video is not long enough', payload.videoUUID, lTags)
|
||||
return
|
||||
}
|
||||
|
||||
const spriteDuration = Math.round(video.duration / totalSprites)
|
||||
|
||||
const spritesCount = findGridSize({
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||
|
||||
import { expect } from 'chai'
|
||||
import { readdir, remove } from 'fs-extra'
|
||||
import { join } from 'path'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
import {
|
||||
cleanupTests,
|
||||
createMultipleServers,
|
||||
doubleFollow,
|
||||
makeGetRequest,
|
||||
PeerTubeServer,
|
||||
setAccessTokensToServers,
|
||||
waitJobs
|
||||
} from '@shared/server-commands'
|
||||
import { SQLCommand } from '../shared'
|
||||
|
||||
function listStoryboardFiles (server: PeerTubeServer) {
|
||||
const storage = server.getDirectoryPath('storyboards')
|
||||
|
||||
return readdir(storage)
|
||||
}
|
||||
|
||||
describe('Test create generate storyboard job', function () {
|
||||
let servers: PeerTubeServer[] = []
|
||||
const uuids: string[] = []
|
||||
let sql: SQLCommand
|
||||
let existingStoryboardName: string
|
||||
|
||||
before(async function () {
|
||||
this.timeout(120000)
|
||||
|
||||
// Run server 2 to have transcoding enabled
|
||||
servers = await createMultipleServers(2)
|
||||
await setAccessTokensToServers(servers)
|
||||
|
||||
await doubleFollow(servers[0], servers[1])
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'video ' + i })
|
||||
uuids.push(uuid)
|
||||
}
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
const storage = servers[0].getDirectoryPath('storyboards')
|
||||
for (const storyboard of await listStoryboardFiles(servers[0])) {
|
||||
await remove(join(storage, storyboard))
|
||||
}
|
||||
|
||||
sql = new SQLCommand(servers[0])
|
||||
await sql.deleteAll('storyboard')
|
||||
|
||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'video 4' })
|
||||
uuids.push(uuid)
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
const storyboards = await listStoryboardFiles(servers[0])
|
||||
existingStoryboardName = storyboards[0]
|
||||
})
|
||||
|
||||
it('Should create a storyboard of a video', async function () {
|
||||
this.timeout(120000)
|
||||
|
||||
for (const uuid of [ uuids[0], uuids[3] ]) {
|
||||
const command = `npm run create-generate-storyboard-job -- -v ${uuid}`
|
||||
await servers[0].cli.execWithEnv(command)
|
||||
}
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
{
|
||||
const storyboards = await listStoryboardFiles(servers[0])
|
||||
expect(storyboards).to.have.lengthOf(2)
|
||||
expect(storyboards).to.not.include(existingStoryboardName)
|
||||
|
||||
existingStoryboardName = storyboards[0]
|
||||
}
|
||||
|
||||
for (const server of servers) {
|
||||
for (const uuid of [ uuids[0], uuids[3] ]) {
|
||||
const { storyboards } = await server.storyboard.list({ id: uuid })
|
||||
expect(storyboards).to.have.lengthOf(1)
|
||||
|
||||
await makeGetRequest({ url: server.url, path: storyboards[0].storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('Should create missing storyboards', async function () {
|
||||
this.timeout(120000)
|
||||
|
||||
const command = `npm run create-generate-storyboard-job -- -a`
|
||||
await servers[0].cli.execWithEnv(command)
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
{
|
||||
const storyboards = await listStoryboardFiles(servers[0])
|
||||
expect(storyboards).to.have.lengthOf(4)
|
||||
expect(storyboards).to.include(existingStoryboardName)
|
||||
}
|
||||
|
||||
for (const server of servers) {
|
||||
for (const uuid of uuids) {
|
||||
const { storyboards } = await server.storyboard.list({ id: uuid })
|
||||
expect(storyboards).to.have.lengthOf(1)
|
||||
|
||||
await makeGetRequest({ url: server.url, path: storyboards[0].storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await sql.cleanup()
|
||||
|
||||
await cleanupTests(servers)
|
||||
})
|
||||
})
|
|
@ -1,5 +1,6 @@
|
|||
// Order of the tests we want to execute
|
||||
import './create-import-video-file-job'
|
||||
import './create-generate-storyboard-job'
|
||||
import './create-move-video-storage-job'
|
||||
import './peertube'
|
||||
import './plugins'
|
||||
|
|
|
@ -268,6 +268,35 @@ cd /var/www/peertube-docker
|
|||
docker-compose exec -u peertube peertube npm run create-move-video-storage-job -- --to-object-storage --all-videos
|
||||
```
|
||||
|
||||
<!-- TODO: uncomment when PeerTube 6 is released
|
||||
### create-generate-storyboard-job
|
||||
|
||||
**PeerTube >= 6.0**
|
||||
|
||||
Use this script to generate storyboard of a specific video:
|
||||
|
||||
```bash
|
||||
# Basic installation
|
||||
cd /var/www/peertube/peertube-latest
|
||||
sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run create-generate-storyboard-job -- -v [videoUUID]
|
||||
|
||||
# Docker installation
|
||||
cd /var/www/peertube-docker
|
||||
docker-compose exec -u peertube peertube npm run create-generate-storyboard-job -- -v [videoUUID]
|
||||
```
|
||||
|
||||
The script can also generate all missing storyboards of local videos:
|
||||
|
||||
```bash
|
||||
# Basic installation
|
||||
cd /var/www/peertube/peertube-latest
|
||||
sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run create-generate-storyboard-job -- --all-videos
|
||||
|
||||
# Docker installation
|
||||
cd /var/www/peertube-docker
|
||||
docker-compose exec -u peertube peertube npm run create-generate-storyboard-job -- --all-videos
|
||||
```
|
||||
-->
|
||||
|
||||
### prune-storage.js
|
||||
|
||||
|
|
Loading…
Reference in New Issue