aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-06-01 14:51:16 +0200
committerChocobozzz <me@florianbigard.com>2023-06-29 10:16:55 +0200
commitd8f39b126d9fe4bec1c12fb213548cc6edc87867 (patch)
tree7f0f1cb23165cf4dd789b2d78b1fef7ee116f647 /shared
parent1fb7d094229acdc190c3f7551b43ac5445814dee (diff)
downloadPeerTube-d8f39b126d9fe4bec1c12fb213548cc6edc87867.tar.gz
PeerTube-d8f39b126d9fe4bec1c12fb213548cc6edc87867.tar.zst
PeerTube-d8f39b126d9fe4bec1c12fb213548cc6edc87867.zip
Add storyboard support
Diffstat (limited to 'shared')
-rw-r--r--shared/ffmpeg/ffmpeg-images.ts37
-rw-r--r--shared/models/activitypub/objects/index.ts2
-rw-r--r--shared/models/activitypub/objects/video-object.ts (renamed from shared/models/activitypub/objects/video-torrent-object.ts)16
-rw-r--r--shared/models/server/custom-config.model.ts4
-rw-r--r--shared/models/server/job.model.ts8
-rw-r--r--shared/models/videos/index.ts1
-rw-r--r--shared/models/videos/storyboard.model.ts11
-rw-r--r--shared/server-commands/server/config-command.ts7
-rw-r--r--shared/server-commands/server/jobs.ts15
-rw-r--r--shared/server-commands/server/server.ts5
-rw-r--r--shared/server-commands/videos/index.ts1
-rw-r--r--shared/server-commands/videos/storyboard-command.ts19
12 files changed, 124 insertions, 2 deletions
diff --git a/shared/ffmpeg/ffmpeg-images.ts b/shared/ffmpeg/ffmpeg-images.ts
index 2db63bd8b..27305382c 100644
--- a/shared/ffmpeg/ffmpeg-images.ts
+++ b/shared/ffmpeg/ffmpeg-images.ts
@@ -56,4 +56,41 @@ export class FFmpegImage {
56 .thumbnail(thumbnailOptions) 56 .thumbnail(thumbnailOptions)
57 }) 57 })
58 } 58 }
59
60 async generateStoryboardFromVideo (options: {
61 path: string
62 destination: string
63
64 sprites: {
65 size: {
66 width: number
67 height: number
68 }
69
70 count: {
71 width: number
72 height: number
73 }
74
75 duration: number
76 }
77 }) {
78 const { path, destination, sprites } = options
79
80 const command = this.commandWrapper.buildCommand(path)
81
82 const filter = [
83 `setpts=N/round(FRAME_RATE)/TB`,
84 `select='not(mod(t,${options.sprites.duration}))'`,
85 `scale=${sprites.size.width}:${sprites.size.height}`,
86 `tile=layout=${sprites.count.width}x${sprites.count.height}`
87 ].join(',')
88
89 command.outputOption('-filter_complex', filter)
90 command.outputOption('-frames:v', '1')
91 command.outputOption('-q:v', '2')
92 command.output(destination)
93
94 return this.commandWrapper.runCommand()
95 }
59} 96}
diff --git a/shared/models/activitypub/objects/index.ts b/shared/models/activitypub/objects/index.ts
index 9aa3c462c..a2e040b32 100644
--- a/shared/models/activitypub/objects/index.ts
+++ b/shared/models/activitypub/objects/index.ts
@@ -6,5 +6,5 @@ export * from './object.model'
6export * from './playlist-element-object' 6export * from './playlist-element-object'
7export * from './playlist-object' 7export * from './playlist-object'
8export * from './video-comment-object' 8export * from './video-comment-object'
9export * from './video-torrent-object' 9export * from './video-object'
10export * from './watch-action-object' 10export * from './watch-action-object'
diff --git a/shared/models/activitypub/objects/video-torrent-object.ts b/shared/models/activitypub/objects/video-object.ts
index 23d54bdbd..a252a2df0 100644
--- a/shared/models/activitypub/objects/video-torrent-object.ts
+++ b/shared/models/activitypub/objects/video-object.ts
@@ -51,6 +51,22 @@ export interface VideoObject {
51 51
52 attributedTo: ActivityPubAttributedTo[] 52 attributedTo: ActivityPubAttributedTo[]
53 53
54 preview?: ActivityPubStoryboard[]
55
54 to?: string[] 56 to?: string[]
55 cc?: string[] 57 cc?: string[]
56} 58}
59
60export interface ActivityPubStoryboard {
61 type: 'Image'
62 rel: [ 'storyboard' ]
63 url: {
64 href: string
65 mediaType: string
66 width: number
67 height: number
68 tileWidth: number
69 tileHeight: number
70 tileDuration: string
71 }[]
72}
diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts
index 4202589f3..1012312f3 100644
--- a/shared/models/server/custom-config.model.ts
+++ b/shared/models/server/custom-config.model.ts
@@ -78,6 +78,10 @@ export interface CustomConfig {
78 torrents: { 78 torrents: {
79 size: number 79 size: number
80 } 80 }
81
82 storyboards: {
83 size: number
84 }
81 } 85 }
82 86
83 signup: { 87 signup: {
diff --git a/shared/models/server/job.model.ts b/shared/models/server/job.model.ts
index 22ecee324..9c40079fb 100644
--- a/shared/models/server/job.model.ts
+++ b/shared/models/server/job.model.ts
@@ -30,6 +30,7 @@ export type JobType =
30 | 'video-studio-edition' 30 | 'video-studio-edition'
31 | 'video-transcoding' 31 | 'video-transcoding'
32 | 'videos-views-stats' 32 | 'videos-views-stats'
33 | 'generate-video-storyboard'
33 34
34export interface Job { 35export interface Job {
35 id: number | string 36 id: number | string
@@ -294,3 +295,10 @@ export interface TranscodingJobBuilderPayload {
294 priority?: number 295 priority?: number
295 }[][] 296 }[][]
296} 297}
298
299// ---------------------------------------------------------------------------
300
301export interface GenerateStoryboardPayload {
302 videoUUID: string
303 federate: boolean
304}
diff --git a/shared/models/videos/index.ts b/shared/models/videos/index.ts
index 80be1854b..b3ce6ad3f 100644
--- a/shared/models/videos/index.ts
+++ b/shared/models/videos/index.ts
@@ -15,6 +15,7 @@ export * from './channel-sync'
15 15
16export * from './nsfw-policy.type' 16export * from './nsfw-policy.type'
17 17
18export * from './storyboard.model'
18export * from './thumbnail.type' 19export * from './thumbnail.type'
19 20
20export * from './video-constant.model' 21export * from './video-constant.model'
diff --git a/shared/models/videos/storyboard.model.ts b/shared/models/videos/storyboard.model.ts
new file mode 100644
index 000000000..c92c81f09
--- /dev/null
+++ b/shared/models/videos/storyboard.model.ts
@@ -0,0 +1,11 @@
1export interface Storyboard {
2 storyboardPath: string
3
4 totalHeight: number
5 totalWidth: number
6
7 spriteHeight: number
8 spriteWidth: number
9
10 spriteDuration: number
11}
diff --git a/shared/server-commands/server/config-command.ts b/shared/server-commands/server/config-command.ts
index b94bd2625..114db8091 100644
--- a/shared/server-commands/server/config-command.ts
+++ b/shared/server-commands/server/config-command.ts
@@ -159,6 +159,10 @@ export class ConfigCommand extends AbstractCommand {
159 newConfig: { 159 newConfig: {
160 transcoding: { 160 transcoding: {
161 enabled: true, 161 enabled: true,
162
163 allowAudioFiles: true,
164 allowAdditionalExtensions: true,
165
162 resolutions: { 166 resolutions: {
163 ...ConfigCommand.getCustomConfigResolutions(false), 167 ...ConfigCommand.getCustomConfigResolutions(false),
164 168
@@ -368,6 +372,9 @@ export class ConfigCommand extends AbstractCommand {
368 }, 372 },
369 torrents: { 373 torrents: {
370 size: 4 374 size: 4
375 },
376 storyboards: {
377 size: 5
371 } 378 }
372 }, 379 },
373 signup: { 380 signup: {
diff --git a/shared/server-commands/server/jobs.ts b/shared/server-commands/server/jobs.ts
index ff3098063..8f131fba4 100644
--- a/shared/server-commands/server/jobs.ts
+++ b/shared/server-commands/server/jobs.ts
@@ -33,6 +33,8 @@ async function waitJobs (
33 33
34 // Check if each server has pending request 34 // Check if each server has pending request
35 for (const server of servers) { 35 for (const server of servers) {
36 if (process.env.DEBUG) console.log('Checking ' + server.url)
37
36 for (const state of states) { 38 for (const state of states) {
37 39
38 const jobPromise = server.jobs.list({ 40 const jobPromise = server.jobs.list({
@@ -45,6 +47,10 @@ async function waitJobs (
45 .then(jobs => { 47 .then(jobs => {
46 if (jobs.length !== 0) { 48 if (jobs.length !== 0) {
47 pendingRequests = true 49 pendingRequests = true
50
51 if (process.env.DEBUG) {
52 console.log(jobs)
53 }
48 } 54 }
49 }) 55 })
50 56
@@ -55,6 +61,10 @@ async function waitJobs (
55 .then(obj => { 61 .then(obj => {
56 if (obj.activityPubMessagesWaiting !== 0) { 62 if (obj.activityPubMessagesWaiting !== 0) {
57 pendingRequests = true 63 pendingRequests = true
64
65 if (process.env.DEBUG) {
66 console.log('AP messages waiting: ' + obj.activityPubMessagesWaiting)
67 }
58 } 68 }
59 }) 69 })
60 tasks.push(debugPromise) 70 tasks.push(debugPromise)
@@ -65,12 +75,15 @@ async function waitJobs (
65 for (const job of data) { 75 for (const job of data) {
66 if (job.state.id !== RunnerJobState.COMPLETED) { 76 if (job.state.id !== RunnerJobState.COMPLETED) {
67 pendingRequests = true 77 pendingRequests = true
78
79 if (process.env.DEBUG) {
80 console.log(job)
81 }
68 } 82 }
69 } 83 }
70 }) 84 })
71 tasks.push(runnerJobsPromise) 85 tasks.push(runnerJobsPromise)
72 } 86 }
73
74 } 87 }
75 88
76 return tasks 89 return tasks
diff --git a/shared/server-commands/server/server.ts b/shared/server-commands/server/server.ts
index 0911e22b0..6aa4296b0 100644
--- a/shared/server-commands/server/server.ts
+++ b/shared/server-commands/server/server.ts
@@ -35,6 +35,7 @@ import {
35 VideoPasswordsCommand, 35 VideoPasswordsCommand,
36 PlaylistsCommand, 36 PlaylistsCommand,
37 ServicesCommand, 37 ServicesCommand,
38 StoryboardCommand,
38 StreamingPlaylistsCommand, 39 StreamingPlaylistsCommand,
39 VideosCommand, 40 VideosCommand,
40 VideoStudioCommand, 41 VideoStudioCommand,
@@ -149,6 +150,8 @@ export class PeerTubeServer {
149 registrations?: RegistrationsCommand 150 registrations?: RegistrationsCommand
150 videoPasswords?: VideoPasswordsCommand 151 videoPasswords?: VideoPasswordsCommand
151 152
153 storyboard?: StoryboardCommand
154
152 runners?: RunnersCommand 155 runners?: RunnersCommand
153 runnerRegistrationTokens?: RunnerRegistrationTokensCommand 156 runnerRegistrationTokens?: RunnerRegistrationTokensCommand
154 runnerJobs?: RunnerJobsCommand 157 runnerJobs?: RunnerJobsCommand
@@ -436,6 +439,8 @@ export class PeerTubeServer {
436 this.videoToken = new VideoTokenCommand(this) 439 this.videoToken = new VideoTokenCommand(this)
437 this.registrations = new RegistrationsCommand(this) 440 this.registrations = new RegistrationsCommand(this)
438 441
442 this.storyboard = new StoryboardCommand(this)
443
439 this.runners = new RunnersCommand(this) 444 this.runners = new RunnersCommand(this)
440 this.runnerRegistrationTokens = new RunnerRegistrationTokensCommand(this) 445 this.runnerRegistrationTokens = new RunnerRegistrationTokensCommand(this)
441 this.runnerJobs = new RunnerJobsCommand(this) 446 this.runnerJobs = new RunnerJobsCommand(this)
diff --git a/shared/server-commands/videos/index.ts b/shared/server-commands/videos/index.ts
index da36b5b6b..106d80af0 100644
--- a/shared/server-commands/videos/index.ts
+++ b/shared/server-commands/videos/index.ts
@@ -11,6 +11,7 @@ export * from './live-command'
11export * from './live' 11export * from './live'
12export * from './playlists-command' 12export * from './playlists-command'
13export * from './services-command' 13export * from './services-command'
14export * from './storyboard-command'
14export * from './streaming-playlists-command' 15export * from './streaming-playlists-command'
15export * from './comments-command' 16export * from './comments-command'
16export * from './video-studio-command' 17export * from './video-studio-command'
diff --git a/shared/server-commands/videos/storyboard-command.ts b/shared/server-commands/videos/storyboard-command.ts
new file mode 100644
index 000000000..06d90fc12
--- /dev/null
+++ b/shared/server-commands/videos/storyboard-command.ts
@@ -0,0 +1,19 @@
1import { HttpStatusCode, Storyboard } from '@shared/models'
2import { AbstractCommand, OverrideCommandOptions } from '../shared'
3
4export class StoryboardCommand extends AbstractCommand {
5
6 list (options: OverrideCommandOptions & {
7 id: number | string
8 }) {
9 const path = '/api/v1/videos/' + options.id + '/storyboards'
10
11 return this.getRequestBody<{ storyboards: Storyboard[] }>({
12 ...options,
13
14 path,
15 implicitToken: true,
16 defaultExpectedStatus: HttpStatusCode.OK_200
17 })
18 }
19}