mirror of https://github.com/Chocobozzz/PeerTube
				
				
				
			
		
			
				
	
	
		
			156 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
 | 
						|
 | 
						|
import { readdir } from 'fs-extra'
 | 
						|
import { omit } from 'lodash'
 | 
						|
import { join } from 'path'
 | 
						|
import { HttpStatusCode, LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoCreateResult, VideoDetails, VideoState } from '@shared/models'
 | 
						|
import { wait } from '../miscs'
 | 
						|
import { unwrapBody } from '../requests'
 | 
						|
import { AbstractCommand, OverrideCommandOptions } from '../shared'
 | 
						|
import { sendRTMPStream, testFfmpegStreamError } from './live'
 | 
						|
 | 
						|
export class LiveCommand extends AbstractCommand {
 | 
						|
 | 
						|
  get (options: OverrideCommandOptions & {
 | 
						|
    videoId: number | string
 | 
						|
  }) {
 | 
						|
    const path = '/api/v1/videos/live'
 | 
						|
 | 
						|
    return this.getRequestBody<LiveVideo>({
 | 
						|
      ...options,
 | 
						|
 | 
						|
      path: path + '/' + options.videoId,
 | 
						|
      implicitToken: true,
 | 
						|
      defaultExpectedStatus: HttpStatusCode.OK_200
 | 
						|
    })
 | 
						|
  }
 | 
						|
 | 
						|
  update (options: OverrideCommandOptions & {
 | 
						|
    videoId: number | string
 | 
						|
    fields: LiveVideoUpdate
 | 
						|
  }) {
 | 
						|
    const { videoId, fields } = options
 | 
						|
    const path = '/api/v1/videos/live'
 | 
						|
 | 
						|
    return this.putBodyRequest({
 | 
						|
      ...options,
 | 
						|
 | 
						|
      path: path + '/' + videoId,
 | 
						|
      fields,
 | 
						|
      implicitToken: true,
 | 
						|
      defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
 | 
						|
    })
 | 
						|
  }
 | 
						|
 | 
						|
  async create (options: OverrideCommandOptions & {
 | 
						|
    fields: LiveVideoCreate
 | 
						|
  }) {
 | 
						|
    const { fields } = options
 | 
						|
    const path = '/api/v1/videos/live'
 | 
						|
 | 
						|
    const attaches: any = {}
 | 
						|
    if (fields.thumbnailfile) attaches.thumbnailfile = fields.thumbnailfile
 | 
						|
    if (fields.previewfile) attaches.previewfile = fields.previewfile
 | 
						|
 | 
						|
    const body = await unwrapBody<{ video: VideoCreateResult }>(this.postUploadRequest({
 | 
						|
      ...options,
 | 
						|
 | 
						|
      path,
 | 
						|
      attaches,
 | 
						|
      fields: omit(fields, 'thumbnailfile', 'previewfile'),
 | 
						|
      implicitToken: true,
 | 
						|
      defaultExpectedStatus: HttpStatusCode.OK_200
 | 
						|
    }))
 | 
						|
 | 
						|
    return body.video
 | 
						|
  }
 | 
						|
 | 
						|
  async sendRTMPStreamInVideo (options: OverrideCommandOptions & {
 | 
						|
    videoId: number | string
 | 
						|
    fixtureName?: string
 | 
						|
    copyCodecs?: boolean
 | 
						|
  }) {
 | 
						|
    const { videoId, fixtureName, copyCodecs } = options
 | 
						|
    const videoLive = await this.get({ videoId })
 | 
						|
 | 
						|
    return sendRTMPStream({ rtmpBaseUrl: videoLive.rtmpUrl, streamKey: videoLive.streamKey, fixtureName, copyCodecs })
 | 
						|
  }
 | 
						|
 | 
						|
  async runAndTestStreamError (options: OverrideCommandOptions & {
 | 
						|
    videoId: number | string
 | 
						|
    shouldHaveError: boolean
 | 
						|
  }) {
 | 
						|
    const command = await this.sendRTMPStreamInVideo(options)
 | 
						|
 | 
						|
    return testFfmpegStreamError(command, options.shouldHaveError)
 | 
						|
  }
 | 
						|
 | 
						|
  waitUntilPublished (options: OverrideCommandOptions & {
 | 
						|
    videoId: number | string
 | 
						|
  }) {
 | 
						|
    const { videoId } = options
 | 
						|
    return this.waitUntilState({ videoId, state: VideoState.PUBLISHED })
 | 
						|
  }
 | 
						|
 | 
						|
  waitUntilWaiting (options: OverrideCommandOptions & {
 | 
						|
    videoId: number | string
 | 
						|
  }) {
 | 
						|
    const { videoId } = options
 | 
						|
    return this.waitUntilState({ videoId, state: VideoState.WAITING_FOR_LIVE })
 | 
						|
  }
 | 
						|
 | 
						|
  waitUntilEnded (options: OverrideCommandOptions & {
 | 
						|
    videoId: number | string
 | 
						|
  }) {
 | 
						|
    const { videoId } = options
 | 
						|
    return this.waitUntilState({ videoId, state: VideoState.LIVE_ENDED })
 | 
						|
  }
 | 
						|
 | 
						|
  waitUntilSegmentGeneration (options: OverrideCommandOptions & {
 | 
						|
    videoUUID: string
 | 
						|
    resolution: number
 | 
						|
    segment: number
 | 
						|
  }) {
 | 
						|
    const { resolution, segment, videoUUID } = options
 | 
						|
    const segmentName = `${resolution}-00000${segment}.ts`
 | 
						|
 | 
						|
    return this.server.servers.waitUntilLog(`${videoUUID}/${segmentName}`, 2, false)
 | 
						|
  }
 | 
						|
 | 
						|
  async waitUntilSaved (options: OverrideCommandOptions & {
 | 
						|
    videoId: number | string
 | 
						|
  }) {
 | 
						|
    let video: VideoDetails
 | 
						|
 | 
						|
    do {
 | 
						|
      video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId })
 | 
						|
 | 
						|
      await wait(500)
 | 
						|
    } while (video.isLive === true || video.state.id !== VideoState.PUBLISHED)
 | 
						|
  }
 | 
						|
 | 
						|
  async countPlaylists (options: OverrideCommandOptions & {
 | 
						|
    videoUUID: string
 | 
						|
  }) {
 | 
						|
    const basePath = this.server.servers.buildDirectory('streaming-playlists')
 | 
						|
    const hlsPath = join(basePath, 'hls', options.videoUUID)
 | 
						|
 | 
						|
    const files = await readdir(hlsPath)
 | 
						|
 | 
						|
    return files.filter(f => f.endsWith('.m3u8')).length
 | 
						|
  }
 | 
						|
 | 
						|
  private async waitUntilState (options: OverrideCommandOptions & {
 | 
						|
    videoId: number | string
 | 
						|
    state: VideoState
 | 
						|
  }) {
 | 
						|
    let video: VideoDetails
 | 
						|
 | 
						|
    do {
 | 
						|
      video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId })
 | 
						|
 | 
						|
      await wait(500)
 | 
						|
    } while (video.state.id !== options.state)
 | 
						|
  }
 | 
						|
}
 |