aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/video/video-file.ts
diff options
context:
space:
mode:
authorRigel Kent <sendmemail@rigelk.eu>2020-03-10 14:39:40 +0100
committerGitHub <noreply@github.com>2020-03-10 14:39:40 +0100
commit8319d6ae72d4da6de51bd3d4b5c68040fc8dc3b4 (patch)
tree1f87041b2cd76222844960602cdc9f52fe206c7b /server/models/video/video-file.ts
parentedb868655e52f934a71141175cf9dc6cb4753e11 (diff)
downloadPeerTube-8319d6ae72d4da6de51bd3d4b5c68040fc8dc3b4.tar.gz
PeerTube-8319d6ae72d4da6de51bd3d4b5c68040fc8dc3b4.tar.zst
PeerTube-8319d6ae72d4da6de51bd3d4b5c68040fc8dc3b4.zip
Add video file metadata to download modal, via ffprobe (#2411)
* Add video file metadata via ffprobe * Federate video file metadata * Add tests for file metadata generation * Complete tests for videoFile metadata federation * Lint migration and video-file for metadata * Objectify metadata from getter in ffmpeg-utils * Add metadataUrl to all videoFiles * Simplify metadata API middleware * Load playlist in videoFile when requesting metadata
Diffstat (limited to 'server/models/video/video-file.ts')
-rw-r--r--server/models/video/video-file.ts96
1 files changed, 86 insertions, 10 deletions
diff --git a/server/models/video/video-file.ts b/server/models/video/video-file.ts
index e08999385..029468004 100644
--- a/server/models/video/video-file.ts
+++ b/server/models/video/video-file.ts
@@ -10,7 +10,9 @@ import {
10 Is, 10 Is,
11 Model, 11 Model,
12 Table, 12 Table,
13 UpdatedAt 13 UpdatedAt,
14 Scopes,
15 DefaultScope
14} from 'sequelize-typescript' 16} from 'sequelize-typescript'
15import { 17import {
16 isVideoFileExtnameValid, 18 isVideoFileExtnameValid,
@@ -29,6 +31,60 @@ import { MVideoFile, MVideoFileStreamingPlaylistVideo, MVideoFileVideo } from '.
29import { MStreamingPlaylistVideo, MVideo } from '@server/typings/models' 31import { MStreamingPlaylistVideo, MVideo } from '@server/typings/models'
30import * as memoizee from 'memoizee' 32import * as memoizee from 'memoizee'
31 33
34export enum ScopeNames {
35 WITH_VIDEO = 'WITH_VIDEO',
36 WITH_VIDEO_OR_PLAYLIST = 'WITH_VIDEO_OR_PLAYLIST',
37 WITH_METADATA = 'WITH_METADATA'
38}
39
40const METADATA_FIELDS = [ 'metadata', 'metadataUrl' ]
41
42@DefaultScope(() => ({
43 attributes: {
44 exclude: [ METADATA_FIELDS[0] ]
45 }
46}))
47@Scopes(() => ({
48 [ScopeNames.WITH_VIDEO]: {
49 include: [
50 {
51 model: VideoModel.unscoped(),
52 required: true
53 }
54 ]
55 },
56 [ScopeNames.WITH_VIDEO_OR_PLAYLIST]: (videoIdOrUUID: string | number) => {
57 const where = (typeof videoIdOrUUID === 'number')
58 ? { id: videoIdOrUUID }
59 : { uuid: videoIdOrUUID }
60
61 return {
62 include: [
63 {
64 model: VideoModel.unscoped(),
65 required: false,
66 where
67 },
68 {
69 model: VideoStreamingPlaylistModel.unscoped(),
70 required: false,
71 include: [
72 {
73 model: VideoModel.unscoped(),
74 required: true,
75 where
76 }
77 ]
78 }
79 ]
80 }
81 },
82 [ScopeNames.WITH_METADATA]: {
83 attributes: {
84 include: METADATA_FIELDS
85 }
86 }
87}))
32@Table({ 88@Table({
33 tableName: 'videoFile', 89 tableName: 'videoFile',
34 indexes: [ 90 indexes: [
@@ -106,6 +162,14 @@ export class VideoFileModel extends Model<VideoFileModel> {
106 @Column 162 @Column
107 fps: number 163 fps: number
108 164
165 @AllowNull(true)
166 @Column(DataType.JSONB)
167 metadata: any
168
169 @AllowNull(true)
170 @Column
171 metadataUrl: string
172
109 @ForeignKey(() => VideoModel) 173 @ForeignKey(() => VideoModel)
110 @Column 174 @Column
111 videoId: number 175 videoId: number
@@ -157,17 +221,29 @@ export class VideoFileModel extends Model<VideoFileModel> {
157 .then(results => results.length === 1) 221 .then(results => results.length === 1)
158 } 222 }
159 223
224 static async doesVideoExistForVideoFile (id: number, videoIdOrUUID: number | string) {
225 const videoFile = await VideoFileModel.loadWithVideoOrPlaylist(id, videoIdOrUUID)
226 return (videoFile?.Video.id === videoIdOrUUID) ||
227 (videoFile?.Video.uuid === videoIdOrUUID) ||
228 (videoFile?.VideoStreamingPlaylist?.Video?.id === videoIdOrUUID) ||
229 (videoFile?.VideoStreamingPlaylist?.Video?.uuid === videoIdOrUUID)
230 }
231
232 static loadWithMetadata (id: number) {
233 return VideoFileModel.scope(ScopeNames.WITH_METADATA).findByPk(id)
234 }
235
160 static loadWithVideo (id: number) { 236 static loadWithVideo (id: number) {
161 const options = { 237 return VideoFileModel.scope(ScopeNames.WITH_VIDEO).findByPk(id)
162 include: [ 238 }
163 {
164 model: VideoModel.unscoped(),
165 required: true
166 }
167 ]
168 }
169 239
170 return VideoFileModel.findByPk(id, options) 240 static loadWithVideoOrPlaylist (id: number, videoIdOrUUID: number | string) {
241 return VideoFileModel.scope({
242 method: [
243 ScopeNames.WITH_VIDEO_OR_PLAYLIST,
244 videoIdOrUUID
245 ]
246 }).findByPk(id)
171 } 247 }
172 248
173 static listByStreamingPlaylist (streamingPlaylistId: number, transaction: Transaction) { 249 static listByStreamingPlaylist (streamingPlaylistId: number, transaction: Transaction) {