Spaces:
Runtime error
Runtime error
| use Monolog\Logger; | |
| class MeltProject | |
| { | |
| private int $width; | |
| private int $height; | |
| private int $frameRateNum; | |
| private int $frameRateDen; | |
| private ?string $audioFile = null; | |
| private string $outputFile; | |
| private array $images; | |
| private Logger $log; | |
| public function __construct(Logger $log, int $width = 1920, int $height = 1080, int $frameRateNum = 25, int $frameRateDen = 1, string $outputFile = './scene.mp4') | |
| { | |
| $this->log = $log; | |
| $this->width = $width; | |
| $this->height = $height; | |
| $this->frameRateNum = $frameRateNum; | |
| $this->frameRateDen = $frameRateDen; | |
| $this->outputFile = $outputFile; | |
| $this->images = []; | |
| $this->log->info('Initialized MeltProject ' . $this); | |
| } | |
| public function __toString() { | |
| return 'width:'.$this->width.' height:'.$this->height . ' framerate:'. $this->frameRateNum . ' outputFile ' . $this->outputFile; | |
| } | |
| public function addImage(string $path, int $in, int $out): void | |
| { | |
| $this->images[] = [ | |
| 'path' => $path, | |
| 'in' => $in, | |
| 'out' => $out | |
| ]; | |
| $this->log->info('Adding image', end($this->images)); | |
| } | |
| /** | |
| * Set the voiceover audio track. | |
| * | |
| * @param string $path | |
| */ | |
| public function setVoiceover(string $path): void | |
| { | |
| $this->audioFile = $path; | |
| $this->log->info('Adding audio track: ' . $path); | |
| } | |
| /** | |
| * Generate the XML document. | |
| * | |
| * @return DOMDocument The generated XML object. | |
| */ | |
| public function generateXml(): DOMDocument | |
| { | |
| $xml = new DOMDocument('1.0', 'utf-8'); | |
| $xml->formatOutput = true; | |
| $mlt = $this->createMltElement($xml); | |
| $xml->appendChild($mlt); | |
| $profile = $this->createProfileElement($xml); | |
| $mlt->appendChild($profile); | |
| $count = 0; | |
| $playlist = $this->createPlaylistElement($xml); | |
| foreach ($this->images as $image) { | |
| $producer = $this->createProducerElement($xml, $image, $count); | |
| $mlt->appendChild($producer); | |
| $entry = $this->createEntryElement($xml, $image, $count); | |
| $playlist->appendChild($entry); | |
| $count++; | |
| } | |
| $mlt->appendChild($playlist); | |
| $tractor0 = $this->createTractorElement($xml, 'tractor0'); | |
| $mlt->appendChild($tractor0); | |
| $multitrack0 = $this->createMultitrackElement($xml); | |
| $tractor0->appendChild($multitrack0); | |
| $imageTrack = $this->createImageTrackElement($xml); | |
| $multitrack0->appendChild($imageTrack); | |
| if ($this->audioFile !== null) { | |
| $voiceoverProducer = $this->createVoiceoverProducerElement($xml, $this->audioFile); | |
| $mlt->appendChild($voiceoverProducer); | |
| $voiceoverPlaylist = $this->createVoiceoverPlaylistElement($xml); | |
| $mlt->appendChild($voiceoverPlaylist); | |
| $voiceoverEntry = $this->createVoiceoverEntryElement($xml); | |
| $voiceoverPlaylist->appendChild($voiceoverEntry); | |
| $tractor1 = $this->createTractorElement($xml, 'tractor1'); | |
| $mlt->appendChild($tractor1); | |
| $multitrack1 = $this->createMultitrackElement($xml); | |
| $tractor1->appendChild($multitrack1); | |
| $trackForTractor0 = $this->createTrackElement($xml, 'tractor0'); | |
| $multitrack1->appendChild($trackForTractor0); | |
| $trackForVoiceoverPlaylist = $this->createTrackElement($xml, 'voiceover_playlist'); | |
| $multitrack1->appendChild($trackForVoiceoverPlaylist); | |
| } | |
| return $xml; | |
| } | |
| private function createMltElement(DOMDocument $xml): DOMElement | |
| { | |
| $mlt = $xml->createElement('mlt'); | |
| $mlt->setAttribute('LC_NUMERIC', 'C'); | |
| $mlt->setAttribute('producer', 'main_bin'); | |
| $mlt->setAttribute('version', '7.12.0'); | |
| $mlt->setAttribute('root', '/home/kash'); | |
| return $mlt; | |
| } | |
| private function createProfileElement(DOMDocument $xml): DOMElement | |
| { | |
| $profile = $xml->createElement('profile'); | |
| $profile->setAttribute('description', 'HD 1080p 25 fps'); | |
| $profile->setAttribute('width', $this->width); | |
| $profile->setAttribute('height', $this->height); | |
| $profile->setAttribute('progressive', '1'); | |
| $profile->setAttribute('sample_aspect_num', '1'); | |
| $profile->setAttribute('sample_aspect_den', '1'); | |
| $profile->setAttribute('display_aspect_num', '16'); | |
| $profile->setAttribute('display_aspect_den', '9'); | |
| $profile->setAttribute('frame_rate_num', $this->frameRateNum); | |
| $profile->setAttribute('frame_rate_den', $this->frameRateDen); | |
| $profile->setAttribute('colorspace', '709'); | |
| return $profile; | |
| } | |
| private function createPlaylistElement(DOMDocument $xml): DOMElement | |
| { | |
| $playlist = $xml->createElement('playlist'); | |
| $playlist->setAttribute('id', 'playlist0'); | |
| return $playlist; | |
| } | |
| private function createProducerElement(DOMDocument $xml, array $image, int $count): DOMElement | |
| { | |
| $producer = $xml->createElement('producer'); | |
| $producer->setAttribute('id', 'producer' . $count); | |
| $producer->setAttribute('in', $image['in']); | |
| $producer->setAttribute('out', $image['out']); | |
| $resource = $xml->createElement('property', $image['path']); | |
| $resource->setAttribute('name', 'resource'); | |
| $producer->appendChild($resource); | |
| $length = $xml->createElement('property', $image['out'] + 1); | |
| $length->setAttribute('name', 'length'); | |
| $producer->appendChild($length); | |
| return $producer; | |
| } | |
| private function createEntryElement(DOMDocument $xml, array $image, int $count): DOMElement | |
| { | |
| $entry = $xml->createElement('entry'); | |
| $entry->setAttribute('producer', 'producer' . $count); | |
| $entry->setAttribute('in', $image['in']); | |
| $entry->setAttribute('out', $image['out']); | |
| return $entry; | |
| } | |
| public function createTractorElement(DOMDocument $xml, string $id): DOMElement | |
| { | |
| $tractor = $xml->createElement('tractor'); | |
| $tractor->setAttribute('id', $id); | |
| return $tractor; | |
| } | |
| public function createTrackElement(DOMDocument $xml, string $producerId): DOMElement | |
| { | |
| $track = $xml->createElement('track'); | |
| $track->setAttribute('producer', $producerId); | |
| return $track; | |
| } | |
| private function createTransitionElement(DOMDocument $xml): DOMElement | |
| { | |
| $transition = $xml->createElement('transition'); | |
| $transition->setAttribute('in', '0'); | |
| $transition->setAttribute('out', $this->images[0]['out']); | |
| $transition->setAttribute('a_track', '0'); | |
| $transition->setAttribute('b_track', '1'); | |
| return $transition; | |
| } | |
| private function createTransitionProperties(): array | |
| { | |
| return [ | |
| ['mlt_service', 'mix'], | |
| ['start', '0'], | |
| ['end', $this->images[0]['out']], | |
| ['a_track', '0'], | |
| ['b_track', '1'], | |
| ]; | |
| } | |
| private function createPropertyElement(DOMDocument $xml, array $property): DOMElement | |
| { | |
| $prop = $xml->createElement('property', $property[1]); | |
| $prop->setAttribute('name', $property[0]); | |
| return $prop; | |
| } | |
| private function createVoiceoverProducerElement(DOMDocument $xml, string $path): DOMElement | |
| { | |
| $producer = $xml->createElement('producer'); | |
| $producer->setAttribute('id', 'voiceover'); | |
| $resource = $xml->createElement('property', $path); | |
| $resource->setAttribute('name', 'resource'); | |
| $producer->appendChild($resource); | |
| return $producer; | |
| } | |
| private function createVoiceoverPlaylistElement(DOMDocument $xml): DOMElement | |
| { | |
| $playlist = $xml->createElement('playlist'); | |
| $playlist->setAttribute('id', 'voiceover_playlist'); | |
| return $playlist; | |
| } | |
| private function createVoiceoverEntryElement(DOMDocument $xml): DOMElement | |
| { | |
| $entry = $xml->createElement('entry'); | |
| $entry->setAttribute('producer', 'voiceover'); | |
| return $entry; | |
| } | |
| private function createMultitrackElement(DOMDocument $xml): DOMElement | |
| { | |
| $multitrack = $xml->createElement('multitrack'); | |
| return $multitrack; | |
| } | |
| private function createVoiceoverTrackElement(DOMDocument $xml): DOMElement | |
| { | |
| $track = $xml->createElement('track'); | |
| $track->setAttribute('producer', 'voiceover_playlist'); | |
| return $track; | |
| } | |
| private function createImageTrackElement(DOMDocument $xml): DOMElement | |
| { | |
| $track = $xml->createElement('track'); | |
| $track->setAttribute('producer', 'playlist0'); | |
| return $track; | |
| } | |
| /** | |
| * Save the MLT project to a file. | |
| * | |
| * @param string $path | |
| * @return bool | |
| */ | |
| public function save(DOMDocument $xml, string $path): bool { | |
| return $xml->save($path) !== false; | |
| } | |
| } |