X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fmodels%2Fvideo%2Fvideo-streaming-playlist.ts;h=b15d20cf92417450e44ed5caa0d4bb7437e5e431;hb=764b1a14fc494f2cfd7ea590d2f07b01df65c7ad;hp=bf6f7b0c4c465ca0a07a2f7bbcd41e7edb7f9b37;hpb=28f3d1b36a70426795240c9370e47b6c4ba847f8;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/models/video/video-streaming-playlist.ts b/server/models/video/video-streaming-playlist.ts index bf6f7b0c4..b15d20cf9 100644 --- a/server/models/video/video-streaming-playlist.ts +++ b/server/models/video/video-streaming-playlist.ts @@ -1,16 +1,27 @@ +import * as memoizee from 'memoizee' +import { join } from 'path' +import { Op } from 'sequelize' import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' -import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' -import { throwIfNotValid } from '../utils' -import { VideoModel } from './video' -import * as Sequelize from 'sequelize' -import { VideoRedundancyModel } from '../redundancy/video-redundancy' +import { doesExist } from '@server/helpers/database-utils' +import { VideoFileModel } from '@server/models/video/video-file' +import { MStreamingPlaylist, MVideo } from '@server/types/models' +import { AttributesOnly } from '@shared/core-utils' import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' -import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' -import { CONSTRAINTS_FIELDS, STATIC_PATHS } from '../../initializers' -import { VideoFileModel } from './video-file' -import { join } from 'path' import { sha1 } from '../../helpers/core-utils' +import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' import { isArrayOf } from '../../helpers/custom-validators/misc' +import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' +import { + CONSTRAINTS_FIELDS, + MEMOIZE_LENGTH, + MEMOIZE_TTL, + P2P_MEDIA_LOADER_PEER_VERSION, + STATIC_PATHS, + WEBSERVER +} from '../../initializers/constants' +import { VideoRedundancyModel } from '../redundancy/video-redundancy' +import { throwIfNotValid } from '../utils' +import { VideoModel } from './video' @Table({ tableName: 'videoStreamingPlaylist', @@ -28,7 +39,7 @@ import { isArrayOf } from '../../helpers/custom-validators/misc' } ] }) -export class VideoStreamingPlaylistModel extends Model { +export class VideoStreamingPlaylistModel extends Model>> { @CreatedAt createdAt: Date @@ -40,7 +51,11 @@ export class VideoStreamingPlaylistModel extends Model throwIfNotValid(value, isActivityPubUrlValid, 'playlist url')) + @Column + playlistFilename: string + + @AllowNull(true) + @Is('PlaylistUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'playlist url', true)) @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.URL.max)) playlistUrl: string @@ -50,7 +65,15 @@ export class VideoStreamingPlaylistModel extends Model throwIfNotValid(value, isActivityPubUrlValid, 'segments sha256 url')) + @Column + p2pMediaLoaderPeerVersion: number + + @AllowNull(false) + @Column + segmentsSha256Filename: string + + @AllowNull(true) + @Is('VideoStreamingSegmentsSha256Url', value => throwIfNotValid(value, isActivityPubUrlValid, 'segments sha256 url', true)) @Column segmentsSha256Url: string @@ -66,6 +89,14 @@ export class VideoStreamingPlaylistModel extends Model VideoFileModel, { + foreignKey: { + allowNull: true + }, + onDelete: 'CASCADE' + }) + VideoFiles: VideoFileModel[] + @HasMany(() => VideoRedundancyModel, { foreignKey: { allowNull: false @@ -75,31 +106,47 @@ export class VideoStreamingPlaylistModel extends Model { - return results.length === 1 - }) + return doesExist(query, { infoHash }) } - static buildP2PMediaLoaderInfoHashes (playlistUrl: string, videoFiles: VideoFileModel[]) { + static buildP2PMediaLoaderInfoHashes (playlistUrl: string, files: unknown[]) { const hashes: string[] = [] - // https://github.com/Novage/p2p-media-loader/blob/master/p2p-media-loader-core/lib/p2p-media-manager.ts#L97 - for (let i = 0; i < videoFiles.length; i++) { - hashes.push(sha1(`1${playlistUrl}+V${i}`)) + // https://github.com/Novage/p2p-media-loader/blob/master/p2p-media-loader-core/lib/p2p-media-manager.ts#L115 + for (let i = 0; i < files.length; i++) { + hashes.push(sha1(`${P2P_MEDIA_LOADER_PEER_VERSION}${playlistUrl}+V${i}`)) } return hashes } + static listByIncorrectPeerVersion () { + const query = { + where: { + p2pMediaLoaderPeerVersion: { + [Op.ne]: P2P_MEDIA_LOADER_PEER_VERSION + } + }, + include: [ + { + model: VideoModel.unscoped(), + required: true + } + ] + } + + return VideoStreamingPlaylistModel.findAll(query) + } + static loadWithVideo (id: number) { const options = { include: [ @@ -110,35 +157,43 @@ export class VideoStreamingPlaylistModel extends Model { + const options = { + where: { + type: VideoStreamingPlaylistType.HLS, + videoId + } + } - static getMasterHlsPlaylistFilename () { - return 'master.m3u8' + return VideoStreamingPlaylistModel.findOne(options) } - static getHlsSha256SegmentsFilename () { - return 'segments-sha256.json' - } + static async loadOrGenerate (video: MVideo) { + let playlist = await VideoStreamingPlaylistModel.loadHLSPlaylistByVideo(video.id) + if (!playlist) playlist = new VideoStreamingPlaylistModel() - static getHlsVideoName (uuid: string, resolution: number) { - return `${uuid}-${resolution}-fragmented.mp4` + return Object.assign(playlist, { videoId: video.id, Video: video }) } - static getHlsMasterPlaylistStaticPath (videoUUID: string) { - return join(STATIC_PATHS.PLAYLISTS.HLS, videoUUID, VideoStreamingPlaylistModel.getMasterHlsPlaylistFilename()) + assignP2PMediaLoaderInfoHashes (video: MVideo, files: unknown[]) { + const masterPlaylistUrl = this.getMasterPlaylistUrl(video) + + this.p2pMediaLoaderInfohashes = VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(masterPlaylistUrl, files) } - static getHlsPlaylistStaticPath (videoUUID: string, resolution: number) { - return join(STATIC_PATHS.PLAYLISTS.HLS, videoUUID, VideoStreamingPlaylistModel.getHlsPlaylistFilename(resolution)) + getMasterPlaylistUrl (video: MVideo) { + if (video.isOwned()) return WEBSERVER.URL + this.getMasterPlaylistStaticPath(video.uuid) + + return this.playlistUrl } - static getHlsSha256SegmentsStaticPath (videoUUID: string) { - return join(STATIC_PATHS.PLAYLISTS.HLS, videoUUID, VideoStreamingPlaylistModel.getHlsSha256SegmentsFilename()) + getSha256SegmentsUrl (video: MVideo) { + if (video.isOwned()) return WEBSERVER.URL + this.getSha256SegmentsStaticPath(video.uuid, video.isLive) + + return this.segmentsSha256Url } getStringType () { @@ -147,12 +202,22 @@ export class VideoStreamingPlaylistModel extends Model