createVideo.ts 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import UploadCommandBase from '../../base/UploadCommandBase'
  2. import { getInputJson } from '../../helpers/InputOutput'
  3. import { videoMetadataFromInput, metadataToBytes } from '../../helpers/serialization'
  4. import { VideoInputParameters, VideoFileMetadata } from '../../Types'
  5. import { CreateInterface } from '@joystream/types'
  6. import { flags } from '@oclif/command'
  7. import { VideoCreationParameters } from '@joystream/types/content'
  8. import { MediaType, VideoMetadata } from '@joystream/content-metadata-protobuf'
  9. import { VideoInputSchema } from '../../json-schemas/ContentDirectory'
  10. import chalk from 'chalk'
  11. export default class CreateVideoCommand extends UploadCommandBase {
  12. static description = 'Create video under specific channel inside content directory.'
  13. static flags = {
  14. input: flags.string({
  15. char: 'i',
  16. required: true,
  17. description: `Path to JSON file to use as input`,
  18. }),
  19. channelId: flags.integer({
  20. char: 'c',
  21. required: true,
  22. description: 'ID of the Channel',
  23. }),
  24. }
  25. setVideoMetadataDefaults(metadata: VideoMetadata, videoFileMetadata: VideoFileMetadata) {
  26. const metaObj = metadata.toObject()
  27. metadata.setDuration((metaObj.duration || videoFileMetadata.duration) as number)
  28. metadata.setMediaPixelWidth((metaObj.mediaPixelWidth || videoFileMetadata.width) as number)
  29. metadata.setMediaPixelHeight((metaObj.mediaPixelHeight || videoFileMetadata.height) as number)
  30. const fileMediaType = new MediaType()
  31. fileMediaType.setCodecName(videoFileMetadata.codecName as string)
  32. fileMediaType.setContainer(videoFileMetadata.container)
  33. fileMediaType.setMimeMediaType(videoFileMetadata.mimeType)
  34. metadata.setMediaType(metadata.getMediaType() || fileMediaType)
  35. }
  36. async run() {
  37. const { input, channelId } = this.parse(CreateVideoCommand).flags
  38. // Get context
  39. const account = await this.getRequiredSelectedAccount()
  40. const channel = await this.getApi().channelById(channelId)
  41. const actor = await this.getChannelOwnerActor(channel)
  42. await this.requestAccountDecoding(account)
  43. // Get input from file
  44. const videoCreationParametersInput = await getInputJson<VideoInputParameters>(input, VideoInputSchema)
  45. const meta = videoMetadataFromInput(videoCreationParametersInput)
  46. // Assets
  47. const { videoPath, thumbnailPhotoPath } = videoCreationParametersInput
  48. const assetsPaths = [videoPath, thumbnailPhotoPath].filter((a) => a !== undefined) as string[]
  49. const inputAssets = await this.prepareInputAssets(assetsPaths, input)
  50. const assets = inputAssets.map(({ parameters }) => ({ Upload: parameters }))
  51. // Set assets indexes in the metadata
  52. if (videoPath) {
  53. meta.setVideo(0)
  54. }
  55. if (thumbnailPhotoPath) {
  56. meta.setThumbnailPhoto(videoPath ? 1 : 0)
  57. }
  58. // Try to get video file metadata
  59. const videoFileMetadata = await this.getVideoFileMetadata(inputAssets[0].path)
  60. this.log('Video media file parameters established:', videoFileMetadata)
  61. this.setVideoMetadataDefaults(meta, videoFileMetadata)
  62. // Create final extrinsic params and send the extrinsic
  63. const videoCreationParameters: CreateInterface<VideoCreationParameters> = {
  64. assets,
  65. meta: metadataToBytes(meta),
  66. }
  67. this.jsonPrettyPrint(JSON.stringify({ assets, metadata: meta.toObject() }))
  68. await this.requireConfirmation('Do you confirm the provided input?', true)
  69. const result = await this.sendAndFollowNamedTx(account, 'content', 'createVideo', [
  70. actor,
  71. channelId,
  72. videoCreationParameters,
  73. ])
  74. if (result) {
  75. const event = this.findEvent(result, 'content', 'VideoCreated')
  76. this.log(chalk.green(`Video with id ${chalk.cyanBright(event?.data[2].toString())} successfully created!`))
  77. }
  78. // Upload assets
  79. await this.uploadAssets(inputAssets, input)
  80. }
  81. }