docs: @Override
  	public void publishVideo(Participant participant, MediaOptions mediaOptions, Integer transactionId)
  			throws OpenViduException {
  
  		Set<Participant> participants = null;
  		String sdpAnswer = null;
  
  		KurentoMediaOptions kurentoOptions = (KurentoMediaOptions) mediaOptions;
  		KurentoParticipant kParticipant = (KurentoParticipant) participant;
  
  		log.debug(
  				"Request [PUBLISH_MEDIA] isOffer={} sdp={} "
  						+ "loopbackAltSrc={} lpbkConnType={} doLoopback={} mediaElements={} ({})",
  				kurentoOptions.isOffer, kurentoOptions.sdpOffer, kurentoOptions.loopbackAlternativeSrc,
  				kurentoOptions.loopbackConnectionType, kurentoOptions.doLoopback, kurentoOptions.mediaElements,
  				participant.getParticipantPublicId());
  
  		SdpType sdpType = kurentoOptions.isOffer ? SdpType.OFFER : SdpType.ANSWER;
  		KurentoSession kSession = kParticipant.getSession();
  
  		kParticipant.createPublishingEndpoint(mediaOptions);
  
  		/*
  		 * for (MediaElement elem : kurentoOptions.mediaElements) {
  		 * kurentoParticipant.getPublisher().apply(elem); }
  		 */
  
  		KurentoTokenOptions kurentoTokenOptions = participant.getToken().getKurentoTokenOptions();
  		if (kurentoOptions.getFilter() != null && kurentoTokenOptions != null) {
  			if (kurentoTokenOptions.isFilterAllowed(kurentoOptions.getFilter().getType())) {
  				this.applyFilterInPublisher(kParticipant, kurentoOptions.getFilter());
  			} else {
  				OpenViduException e = new OpenViduException(Code.FILTER_NOT_APPLIED_ERROR_CODE,
  						"Error applying filter for publishing user " + participant.getParticipantPublicId()
  								+ ". The token has no permissions to apply filter "
  								+ kurentoOptions.getFilter().getType());
  				log.error("PARTICIPANT {}: Error applying filter. The token has no permissions to apply filter {}",
  						participant.getParticipantPublicId(), kurentoOptions.getFilter().getType(), e);
  				sessionEventsHandler.onPublishMedia(participant, null, kParticipant.getPublisher().createdAt(),
  						kSession.getSessionId(), mediaOptions, sdpAnswer, participants, transactionId, e);
  				throw e;
  			}
  		}
  
  		sdpAnswer = kParticipant.publishToRoom(sdpType, kurentoOptions.sdpOffer, kurentoOptions.doLoopback,
  				kurentoOptions.loopbackAlternativeSrc, kurentoOptions.loopbackConnectionType);
  
  		if (sdpAnswer == null) {
  			OpenViduException e = new OpenViduException(Code.MEDIA_SDP_ERROR_CODE,
  					"Error generating SDP response for publishing user " + participant.getParticipantPublicId());
  			log.error("PARTICIPANT {}: Error publishing media", participant.getParticipantPublicId(), e);
  			sessionEventsHandler.onPublishMedia(participant, null, kParticipant.getPublisher().createdAt(),
  					kSession.getSessionId(), mediaOptions, sdpAnswer, participants, transactionId, e);
  		}
  
  		if (this.openviduConfig.isRecordingModuleEnabled()
  				&& MediaMode.ROUTED.equals(kSession.getSessionProperties().mediaMode())
  				&& kSession.getActivePublishers() == 0) {
  			if (RecordingMode.ALWAYS.equals(kSession.getSessionProperties().recordingMode())
  					&& !recordingManager.sessionIsBeingRecorded(kSession.getSessionId())
  					&& !kSession.recordingManuallyStopped.get()) {
  				// Start automatic recording for sessions configured with RecordingMode.ALWAYS
  				new Thread(() -> {
  					recordingManager.startRecording(kSession,
  							new RecordingProperties.Builder().name("")
  									.outputMode(kSession.getSessionProperties().defaultOutputMode())
  									.recordingLayout(kSession.getSessionProperties().defaultRecordingLayout())
  									.customLayout(kSession.getSessionProperties().defaultCustomLayout()).build());
  				}).start();
  			} else if (RecordingMode.MANUAL.equals(kSession.getSessionProperties().recordingMode())
  					&& recordingManager.sessionIsBeingRecorded(kSession.getSessionId())) {
  				// Abort automatic recording stop (user published before timeout)
  				log.info("Participant {} published before timeout finished. Aborting automatic recording stop",
  						participant.getParticipantPublicId());
  				boolean stopAborted = recordingManager.abortAutomaticRecordingStopThread(kSession);
  				if (stopAborted) {
  					log.info("Automatic recording stopped succesfully aborted");
  				} else {
  					log.info("Automatic recording stopped couldn't be aborted. Recording of session {} has stopped",
  							kSession.getSessionId());
  				}
  			}
  		}
  
  		kSession.newPublisher(participant);
  
  		participants = kParticipant.getSession().getParticipants();
  
  		if (sdpAnswer != null) {
  			sessionEventsHandler.onPublishMedia(participant, participant.getPublisherStreamId(),
  					kParticipant.getPublisher().createdAt(), kSession.getSessionId(), mediaOptions, sdpAnswer,
  					participants, transactionId, null);
  		}
  	}