mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-05 02:39:33 +02:00
Improve Video
AP compatibility
Compat with text/html descriptions Compat with SPDX for licences Compat with missing sensitive attribute Compat with missing tag attribute Compat with missing video file magnet URI Compat with missing streaming playlist segmentsSha256Url Compat with optional comments/likes/dislikes/shares URI in video object Add more debug logs when the object is not valid
This commit is contained in:
parent
1e3a5b25c3
commit
7c9f07e140
13 changed files with 215 additions and 124 deletions
|
@ -16,7 +16,6 @@ import { isAPVideoFileUrlMetadataObject } from '@server/helpers/custom-validator
|
|||
import { isArray } from '@server/helpers/custom-validators/misc.js'
|
||||
import { isVideoFileInfoHashValid } from '@server/helpers/custom-validators/videos.js'
|
||||
import { generateImageFilename } from '@server/helpers/image-utils.js'
|
||||
import { logger } from '@server/helpers/logger.js'
|
||||
import { getExtFromMimetype } from '@server/helpers/video.js'
|
||||
import { MIMETYPES, P2P_MEDIA_LOADER_PEER_VERSION, PREVIEWS_SIZE, THUMBNAILS_SIZE } from '@server/initializers/constants.js'
|
||||
import { generateTorrentFileName } from '@server/lib/paths.js'
|
||||
|
@ -58,21 +57,6 @@ export function getFileAttributesFromUrl (
|
|||
|
||||
const attributes: FilteredModelAttributes<VideoFileModel>[] = []
|
||||
for (const fileUrl of fileUrls) {
|
||||
// Fetch associated magnet uri
|
||||
const magnet = urls.filter(isAPMagnetUrlObject)
|
||||
.find(u => u.height === fileUrl.height)
|
||||
|
||||
if (!magnet) throw new Error('Cannot find associated magnet uri for file ' + fileUrl.href)
|
||||
|
||||
const parsed = magnetUriDecode(magnet.href)
|
||||
if (!parsed || isVideoFileInfoHashValid(parsed.infoHash) === false) {
|
||||
throw new Error('Cannot parse magnet URI ' + magnet.href)
|
||||
}
|
||||
|
||||
const torrentUrl = Array.isArray(parsed.xs)
|
||||
? parsed.xs[0]
|
||||
: parsed.xs
|
||||
|
||||
// Fetch associated metadata url, if any
|
||||
const metadata = urls.filter(isAPVideoFileUrlMetadataObject)
|
||||
.find(u => {
|
||||
|
@ -84,14 +68,20 @@ export function getFileAttributesFromUrl (
|
|||
const extname = getExtFromMimetype(MIMETYPES.VIDEO.MIMETYPE_EXT, fileUrl.mediaType)
|
||||
const resolution = fileUrl.height
|
||||
const videoId = isStreamingPlaylist(videoOrPlaylist) ? null : videoOrPlaylist.id
|
||||
const videoStreamingPlaylistId = isStreamingPlaylist(videoOrPlaylist) ? videoOrPlaylist.id : null
|
||||
|
||||
const videoStreamingPlaylistId = isStreamingPlaylist(videoOrPlaylist)
|
||||
? videoOrPlaylist.id
|
||||
: null
|
||||
|
||||
const { torrentFilename, infoHash, torrentUrl } = getTorrentRelatedInfo({ videoOrPlaylist, urls, fileUrl })
|
||||
|
||||
const attribute = {
|
||||
extname,
|
||||
infoHash: parsed.infoHash,
|
||||
resolution,
|
||||
|
||||
size: fileUrl.size,
|
||||
fps: fileUrl.fps || -1,
|
||||
|
||||
metadataUrl: metadata?.href,
|
||||
|
||||
width: fileUrl.width,
|
||||
|
@ -101,9 +91,9 @@ export function getFileAttributesFromUrl (
|
|||
filename: basename(fileUrl.href),
|
||||
fileUrl: fileUrl.href,
|
||||
|
||||
infoHash,
|
||||
torrentFilename,
|
||||
torrentUrl,
|
||||
// Use our own torrent name since we proxify torrent requests
|
||||
torrentFilename: generateTorrentFileName(videoOrPlaylist, resolution),
|
||||
|
||||
// This is a video file owned by a video or by a streaming playlist
|
||||
videoId,
|
||||
|
@ -126,19 +116,17 @@ export function getStreamingPlaylistAttributesFromObject (video: MVideoId, video
|
|||
|
||||
const files: unknown[] = playlistUrlObject.tag.filter(u => isAPVideoUrlObject(u)) as ActivityVideoUrlObject[]
|
||||
|
||||
if (!segmentsSha256UrlObject) {
|
||||
logger.warn('No segment sha256 URL found in AP playlist object.', { playlistUrl: playlistUrlObject })
|
||||
continue
|
||||
}
|
||||
|
||||
const attribute = {
|
||||
type: VideoStreamingPlaylistType.HLS,
|
||||
|
||||
playlistFilename: basename(playlistUrlObject.href),
|
||||
playlistUrl: playlistUrlObject.href,
|
||||
|
||||
segmentsSha256Filename: basename(segmentsSha256UrlObject.href),
|
||||
segmentsSha256Url: segmentsSha256UrlObject.href,
|
||||
segmentsSha256Filename: segmentsSha256UrlObject
|
||||
? basename(segmentsSha256UrlObject.href)
|
||||
: null,
|
||||
|
||||
segmentsSha256Url: segmentsSha256UrlObject?.href ?? null,
|
||||
|
||||
p2pMediaLoaderInfohashes: VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(playlistUrlObject.href, files),
|
||||
p2pMediaLoaderPeerVersion: P2P_MEDIA_LOADER_PEER_VERSION,
|
||||
|
@ -270,3 +258,41 @@ function isAPMagnetUrlObject (url: any): url is ActivityMagnetUrlObject {
|
|||
function isAPHashTagObject (url: any): url is ActivityHashTagObject {
|
||||
return url && url.type === 'Hashtag'
|
||||
}
|
||||
|
||||
function getTorrentRelatedInfo (options: {
|
||||
videoOrPlaylist: MVideo | MStreamingPlaylistVideo
|
||||
urls: (ActivityTagObject | ActivityUrlObject)[]
|
||||
fileUrl: ActivityVideoUrlObject
|
||||
}) {
|
||||
const { urls, fileUrl, videoOrPlaylist } = options
|
||||
|
||||
// Fetch associated magnet uri
|
||||
const magnet = urls.filter(isAPMagnetUrlObject)
|
||||
.find(u => u.height === fileUrl.height)
|
||||
|
||||
if (!magnet) {
|
||||
return {
|
||||
torrentUrl: null,
|
||||
torrentFilename: null,
|
||||
infoHash: null
|
||||
}
|
||||
}
|
||||
|
||||
const magnetParsed = magnetUriDecode(magnet.href)
|
||||
if (magnetParsed && isVideoFileInfoHashValid(magnetParsed.infoHash) === false) {
|
||||
throw new Error('Info hash is not valid in magnet URI ' + magnet.href)
|
||||
}
|
||||
|
||||
const torrentUrl = Array.isArray(magnetParsed.xs)
|
||||
? magnetParsed.xs[0]
|
||||
: magnetParsed.xs
|
||||
|
||||
return {
|
||||
torrentUrl,
|
||||
|
||||
// Use our own torrent name since we proxify torrent requests
|
||||
torrentFilename: generateTorrentFileName(videoOrPlaylist, fileUrl.height),
|
||||
|
||||
infoHash: magnetParsed.infoHash
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,8 @@ async function getRatesCount (type: 'like' | 'dislike', video: MVideo, fetchedVi
|
|||
? fetchedVideo.likes
|
||||
: fetchedVideo.dislikes
|
||||
|
||||
if (!uri) return
|
||||
|
||||
logger.info('Sync %s of video %s', type, video.url)
|
||||
|
||||
const { body } = await fetchAP<ActivityPubOrderedCollection<any>>(uri)
|
||||
|
@ -70,6 +72,7 @@ async function getRatesCount (type: 'like' | 'dislike', video: MVideo, fetchedVi
|
|||
|
||||
function syncShares (video: MVideo, fetchedVideo: VideoObject, isSync: boolean) {
|
||||
const uri = fetchedVideo.shares
|
||||
if (!uri) return
|
||||
|
||||
if (!isSync) {
|
||||
return createJob({ uri, videoId: video.id, type: 'video-shares' })
|
||||
|
@ -84,6 +87,7 @@ function syncShares (video: MVideo, fetchedVideo: VideoObject, isSync: boolean)
|
|||
|
||||
function syncComments (video: MVideo, fetchedVideo: VideoObject, isSync: boolean) {
|
||||
const uri = fetchedVideo.comments
|
||||
if (!uri) return
|
||||
|
||||
if (!isSync) {
|
||||
return createJob({ uri, videoId: video.id, type: 'video-comments' })
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue