private final void genVideo() {
		File inputFile = this.getVideoFileSource();
		if (inputFile == null) {
			if (this.isOutputEncoding()) this.encodeAll(2, "No video input");
			return;
		}

		final Videncode self = this;
		String filename = "output";
		double[] time = this.getVideoFileSourceEncodeDuration();
		double length = time[1] - time[0];
		if (length <= 0.0) {
			if (this.isOutputEncoding()) this.encodeAll(2, "No duration");
			return;
		}
		double start = time[0];
		Dimension size = this.getVideoFileTempDimensions();
		FrameRate framerate = this.getVideoFileTempFrameRate();
		int threads = this.getVideoFileTempEncodingThreads();
		int quality = this.getVideoFileTempQuality();
		boolean reEncodePossible;

		long max = this.getOutputMaxFileSize();
		long imageSize = this.getImageFileTempFileSize();
		long audioSize = this.getAudioFileTempFileSize();
		long metadataSize = this.getOutputMetadataLength();
		max -= imageSize + audioSize + metadataSize;
		if (max <= 0) {
			if (this.isOutputEncoding()) this.encodeAll(2, "No space");
			return;
		}

		Bitrate bitrate = new Bitrate((int) (max * 8 / length), "");

		this.cancelVideoTempFileEncoding();
		if (this.deleteVideoFileTempFile()) {
			this.signalChange(new VidencodeChangeEvent(
				this,
				VidencodeChangeEvent.EventType.VIDEO_FILE_CHANGED,
				VidencodeChangeEvent.TEMPORARY | VidencodeChangeEvent.UPDATING
			));
		}

		GeneratorProgressCallback callback = new GeneratorProgressCallback() {
			@Override
			public final void onProgress(double progress, int flags) {
				self.onVideoProgress(progress);
			}
		};

		synchronized (this.videoFileTempLock) {
			this.videoFileTempIsGenerating = true;
			this.videoFileTempGeneratingPercent = 0.0;
			reEncodePossible = this.videoFileTempMightNeedReEncoding;
			this.videoFileTempMightNeedReEncoding = false;
		}

		this.signalChange(new VidencodeChangeEvent(
			this,
			VidencodeChangeEvent.EventType.VIDEO_FILE_ENCODING_LOG,
			VidencodeChangeEvent.CLEAR
		));
		this.videoFileTempGenerator = new VideoGenerator(
			this,
			inputFile,
			filename,
			this.getTempDir(),
			start,
			length,
			bitrate,
			size,
			framerate,
			callback,
			threads,
			quality,
			max,
			reEncodePossible,
			this.parseCommandOptions(this.extraFFmpegOptions[0])
		){
			@Override
			public void onVideoGet(File f) {
				self.onVideoCompleted(f);
			}
			@Override
			protected void onCommandGenerate(final String str) {
				self.signalChange(new VidencodeChangeEvent(
					self,
					VidencodeChangeEvent.EventType.VIDEO_FILE_ENCODING_LOG,
					0
				).setText(0, str));
			}
			@Override
			protected void onInfoUpdate(final String str) {
				self.signalChange(new VidencodeChangeEvent(
					self,
					VidencodeChangeEvent.EventType.VIDEO_FILE_ENCODING_LOG,
					0
				).setText(1, str));
			}
			@Override
			protected void onProgressStringUpdate(final String str) {
				self.signalChange(new VidencodeChangeEvent(
					self,
					VidencodeChangeEvent.EventType.VIDEO_FILE_ENCODING_LOG,
					0
				).setText(2, str));
			}
		};
		this.videoFileTempGenerator.start();
	}