diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts index b9fc5e792..a86def936 100644 --- a/server/lib/activitypub/process/process-delete.ts +++ b/server/lib/activitypub/process/process-delete.ts @@ -5,11 +5,11 @@ import { sequelizeTypescript } from '../../../initializers/database' import { ActorModel } from '../../../models/activitypub/actor' import { VideoModel } from '../../../models/video/video' import { VideoCommentModel } from '../../../models/video/video-comment' -import { markCommentAsDeleted } from '../../video-comment' -import { forwardVideoRelatedActivity } from '../send/utils' import { VideoPlaylistModel } from '../../../models/video/video-playlist' import { APProcessorOptions } from '../../../types/activitypub-processor.model' -import { MAccountActor, MActor, MActorSignature, MChannelActor, MChannelActorAccountActor } from '../../../types/models' +import { MAccountActor, MActor, MActorSignature, MChannelActor, MChannelActorAccountActor, MCommentOwnerVideo } from '../../../types/models' +import { markCommentAsDeleted } from '../../video-comment' +import { forwardVideoRelatedActivity } from '../send/utils' async function processDeleteActivity (options: APProcessorOptions) { const { activity, byActor } = options @@ -121,7 +121,10 @@ async function processDeleteVideoChannel (videoChannelToRemove: MChannelActor) { logger.info('Remote video channel %s removed.', videoChannelToRemove.Actor.url) } -function processDeleteVideoComment (byActor: MActorSignature, videoComment: VideoCommentModel, activity: ActivityDelete) { +function processDeleteVideoComment (byActor: MActorSignature, videoComment: MCommentOwnerVideo, activity: ActivityDelete) { + // Already deleted + if (videoComment.isDeleted()) return + logger.debug('Removing remote video comment "%s".', videoComment.url) return sequelizeTypescript.transaction(async t => { diff --git a/server/lib/live-manager.ts b/server/lib/live-manager.ts index ef50e3cdb..5d9b68756 100644 --- a/server/lib/live-manager.ts +++ b/server/lib/live-manager.ts @@ -287,16 +287,17 @@ class LiveManager { for (let i = 0; i < allResolutions.length; i++) { const resolution = allResolutions[i] - VideoFileModel.upsert({ + const file = new VideoFileModel({ resolution, size: -1, extname: '.ts', infoHash: null, fps, videoStreamingPlaylistId: playlist.id - }).catch(err => { - logger.error('Cannot create file for live streaming.', { err }) }) + + VideoFileModel.customUpsert(file, 'streaming-playlist', null) + .catch(err => logger.error('Cannot create file for live streaming.', { err })) } const outPath = getHLSDirectory(videoLive.Video) diff --git a/server/tests/api/check-params/live.ts b/server/tests/api/check-params/live.ts index 40dca908b..7e76caf6e 100644 --- a/server/tests/api/check-params/live.ts +++ b/server/tests/api/check-params/live.ts @@ -22,7 +22,7 @@ import { updateLive, uploadVideoAndGetId, userLogin, - waitUntilLiveStarts + waitUntilLivePublished } from '../../../../shared/extra-utils' import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' @@ -409,7 +409,7 @@ describe('Test video lives API validator', function () { const command = sendRTMPStream(live.rtmpUrl, live.streamKey) - await waitUntilLiveStarts(server.url, server.accessToken, videoId) + await waitUntilLivePublished(server.url, server.accessToken, videoId) await updateLive(server.url, server.accessToken, videoId, {}, HttpStatusCode.BAD_REQUEST_400) await stopFfmpeg(command) @@ -423,7 +423,7 @@ describe('Test video lives API validator', function () { const command = sendRTMPStream(live.rtmpUrl, live.streamKey) - await waitUntilLiveStarts(server.url, server.accessToken, videoId) + await waitUntilLivePublished(server.url, server.accessToken, videoId) await runAndTestFfmpegStreamError(server.url, server.accessToken, videoId, true) diff --git a/server/tests/api/live/live-permanent.ts b/server/tests/api/live/live-permanent.ts index 54e4010e9..2701c65e3 100644 --- a/server/tests/api/live/live-permanent.ts +++ b/server/tests/api/live/live-permanent.ts @@ -20,7 +20,7 @@ import { updateLive, wait, waitJobs, - waitUntilLiveStarts + waitUntilLivePublished } from '../../../../shared/extra-utils' const expect = chai.expect @@ -116,7 +116,7 @@ describe('Permenant live', function () { const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, videoUUID) for (const server of servers) { - await waitUntilLiveStarts(server.url, server.accessToken, videoUUID) + await waitUntilLivePublished(server.url, server.accessToken, videoUUID) } await checkVideoState(videoUUID, VideoState.PUBLISHED) @@ -171,7 +171,7 @@ describe('Permenant live', function () { const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, videoUUID) for (const server of servers) { - await waitUntilLiveStarts(server.url, server.accessToken, videoUUID) + await waitUntilLivePublished(server.url, server.accessToken, videoUUID) } await checkVideoState(videoUUID, VideoState.PUBLISHED) diff --git a/server/tests/api/live/live-save-replay.ts b/server/tests/api/live/live-save-replay.ts index e300ec345..bd683b2bf 100644 --- a/server/tests/api/live/live-save-replay.ts +++ b/server/tests/api/live/live-save-replay.ts @@ -23,7 +23,7 @@ import { updateCustomSubConfig, updateVideo, waitJobs, - waitUntilLiveStarts + waitUntilLivePublished } from '../../../../shared/extra-utils' import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' @@ -127,7 +127,7 @@ describe('Save replay setting', function () { this.timeout(20000) ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoUUID) await waitJobs(servers) @@ -156,7 +156,7 @@ describe('Save replay setting', function () { liveVideoUUID = await createLiveWrapper(false) ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoUUID) await waitJobs(servers) await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) @@ -182,7 +182,7 @@ describe('Save replay setting', function () { liveVideoUUID = await createLiveWrapper(false) ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoUUID) await waitJobs(servers) await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) @@ -216,7 +216,7 @@ describe('Save replay setting', function () { this.timeout(20000) ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoUUID) await waitJobs(servers) @@ -259,7 +259,7 @@ describe('Save replay setting', function () { liveVideoUUID = await createLiveWrapper(true) ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoUUID) await waitJobs(servers) await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) @@ -285,7 +285,7 @@ describe('Save replay setting', function () { liveVideoUUID = await createLiveWrapper(true) ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoUUID) await waitJobs(servers) await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts index a74988aba..7ea0ec198 100644 --- a/server/tests/api/live/live.ts +++ b/server/tests/api/live/live.ts @@ -7,6 +7,7 @@ import { join } from 'path' import { ffprobePromise, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils' import { getLiveNotificationSocket } from '@shared/extra-utils/socket/socket-io' import { LiveVideo, LiveVideoCreate, Video, VideoDetails, VideoPrivacy, VideoState, VideoStreamingPlaylistType } from '@shared/models' +import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { addVideoToBlacklist, buildServerDirectory, @@ -41,10 +42,9 @@ import { waitJobs, waitUntilLiveEnded, waitUntilLivePublished, - waitUntilLiveStarts, + waitUntilLiveSegmentGeneration, waitUntilLog } from '../../../../shared/extra-utils' -import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' const expect = chai.expect @@ -329,8 +329,9 @@ describe('Test live', function () { await checkResolutionsInMasterPlaylist(hlsPlaylist.playlistUrl, resolutions) for (let i = 0; i < resolutions.length; i++) { - const segmentName = `${i}-000001.ts` - await waitUntilLog(servers[0], `${video.uuid}/${segmentName}`, 2, false) + const segmentNum = 1 + const segmentName = `${i}-00000${segmentNum}.ts` + await waitUntilLiveSegmentGeneration(servers[0], video.uuid, i, segmentNum) const res = await getPlaylist(`${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8`) const subPlaylist = res.text @@ -374,7 +375,7 @@ describe('Test live', function () { liveVideoId = await createLiveWrapper(false) const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId) await waitJobs(servers) await testVideoResolutions(liveVideoId, [ 720 ]) @@ -390,7 +391,7 @@ describe('Test live', function () { liveVideoId = await createLiveWrapper(false) const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId) await waitJobs(servers) await testVideoResolutions(liveVideoId, resolutions) @@ -407,7 +408,7 @@ describe('Test live', function () { liveVideoId = await createLiveWrapper(true) const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId, 'video_short2.webm') - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId) await waitJobs(servers) await testVideoResolutions(liveVideoId, resolutions) @@ -495,7 +496,7 @@ describe('Test live', function () { liveVideoId = res.body.video.uuid command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId) await waitJobs(servers) }) @@ -584,7 +585,7 @@ describe('Test live', function () { const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) for (const server of servers) { - await waitUntilLiveStarts(server.url, server.accessToken, liveVideoUUID) + await waitUntilLivePublished(server.url, server.accessToken, liveVideoUUID) } await waitJobs(servers) @@ -623,7 +624,7 @@ describe('Test live', function () { socket.emit('subscribe', { videoId }) const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) - await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) + await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoUUID) await waitJobs(servers) expect(stateChanges).to.have.lengthOf(1) @@ -653,7 +654,7 @@ describe('Test live', function () { } before(async function () { - this.timeout(60000) + this.timeout(120000) liveVideoId = await createLiveWrapper(false) liveVideoReplayId = await createLiveWrapper(true) @@ -664,10 +665,13 @@ describe('Test live', function () { ]) await Promise.all([ - waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId), - waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoReplayId) + waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId), + waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId) ]) + await waitUntilLiveSegmentGeneration(servers[0], liveVideoId, 0, 2) + await waitUntilLiveSegmentGeneration(servers[0], liveVideoReplayId, 0, 2) + await killallServers([ servers[0] ]) await reRunServer(servers[0]) @@ -677,14 +681,11 @@ describe('Test live', function () { it('Should cleanup lives', async function () { this.timeout(60000) - const res = await getVideo(servers[0].url, liveVideoId) - const video: VideoDetails = res.body - - expect(video.state.id).to.equal(VideoState.LIVE_ENDED) + await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId) }) it('Should save a live replay', async function () { - this.timeout(60000) + this.timeout(120000) await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId) }) diff --git a/shared/extra-utils/videos/live.ts b/shared/extra-utils/videos/live.ts index 4aa66622b..cbcfc09e4 100644 --- a/shared/extra-utils/videos/live.ts +++ b/shared/extra-utils/videos/live.ts @@ -6,11 +6,11 @@ import { pathExists, readdir } from 'fs-extra' import { omit } from 'lodash' import { join } from 'path' import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoDetails, VideoState } from '@shared/models' +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { buildAbsoluteFixturePath, buildServerDirectory, wait } from '../miscs/miscs' import { makeGetRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests' -import { ServerInfo } from '../server/servers' +import { ServerInfo, waitUntilLog } from '../server/servers' import { getVideoWithToken } from './videos' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' function getLive (url: string, token: string, videoId: number | string, statusCodeExpected = HttpStatusCode.OK_200) { const path = '/api/v1/videos/live' @@ -136,19 +136,20 @@ async function stopFfmpeg (command: ffmpeg.FfmpegCommand) { await wait(500) } -function waitUntilLiveStarts (url: string, token: string, videoId: number | string) { - return waitWhileLiveState(url, token, videoId, VideoState.WAITING_FOR_LIVE) -} - function waitUntilLivePublished (url: string, token: string, videoId: number | string) { - return waitWhileLiveState(url, token, videoId, VideoState.PUBLISHED) + return waitUntilLiveState(url, token, videoId, VideoState.PUBLISHED) } function waitUntilLiveEnded (url: string, token: string, videoId: number | string) { - return waitWhileLiveState(url, token, videoId, VideoState.LIVE_ENDED) + return waitUntilLiveState(url, token, videoId, VideoState.LIVE_ENDED) } -async function waitWhileLiveState (url: string, token: string, videoId: number | string, state: VideoState) { +function waitUntilLiveSegmentGeneration (server: ServerInfo, videoUUID: string, resolutionNum: number, segmentNum: number) { + const segmentName = `${resolutionNum}-00000${segmentNum}.ts` + return waitUntilLog(server, `${videoUUID}/${segmentName}`, 2, false) +} + +async function waitUntilLiveState (url: string, token: string, videoId: number | string, state: VideoState) { let video: VideoDetails do { @@ -156,7 +157,7 @@ async function waitWhileLiveState (url: string, token: string, videoId: number | video = res.body await wait(500) - } while (video.state.id === state) + } while (video.state.id !== state) } async function checkLiveCleanup (server: ServerInfo, videoUUID: string, resolutions: number[] = []) { @@ -200,10 +201,10 @@ export { getPlaylistsCount, waitUntilLivePublished, updateLive, - waitUntilLiveStarts, createLive, runAndTestFfmpegStreamError, checkLiveCleanup, + waitUntilLiveSegmentGeneration, stopFfmpeg, sendRTMPStreamInVideo, waitUntilLiveEnded,