def __cut_audio__(session_id, edit_info): """ Given a rumba session and the information to mount a video, it cuts the session audio to fit into the mounted video. For this, it takes into account the timestamp of the first frame of the video to mount and the timestamp of the last frame of this new video. VERY IMPORTANT: This method assumes that the timestamps of video and audio are consistent in terms of synchronization. :param session_id: Id of the rumba session. :param edit_info: The informtion provided by the editor containing the list of video slices. :return: Absolute path where the audio cut by this method is located. """ session = RumbaSession.objects(id=session_id).first() if session is None: raise NotExistingResource("There's no session with such id.") audio_path = "{}/audio.wav".format(session['folder_url']) video_init_ts = VideoEditorHelper.get_first_video_ts(edit_info=edit_info) audio_init_ts = AudioManager.get_instance().get_audio_init_ts(session_id=session_id) audio_init_offset = VideoEditorHelper.calculate_audio_init_offset(audio_init_ts=audio_init_ts, video_init_ts=video_init_ts) ffmpeg_audio_init_offset = DataTransformer.transform_seconds_to_ffmpeg_offset(float(audio_init_offset)) audio_init_ts = AudioManager.get_instance().get_audio_init_ts(session_id=session_id) audio_end_offset = VideoEditorHelper.calculate_audio_end_offset(audio_init_ts=audio_init_ts, edit_info=edit_info, audio_init_offset=audio_init_offset) audio_output = "{}/audio-{}.wav".format(session['folder_url'], uuid.uuid4().hex) audio_thread = AudioSplitterThread(inputFile=audio_path, outputFile=audio_output, initial_offset=ffmpeg_audio_init_offset, end_offset=audio_end_offset) audio_thread.start() audio_thread.join() if audio_thread.code != 0: raise Exception("FFMpeg command failed.") return audio_output
def stop_session(self, session_id): """ Stops an active session. Stopping a session means that no more users would be able to stream video to the server. Of course, only active sessions could be stopped. :param session_id: Id of the session to stop. :raises: - ValueError, if the specified id is not valid. - IllegalSessionStateException: If the session was not active. """ LOGGER.info("Stopping session: [id={}]".format(session_id)) GenericValidator.validate_id(session_id) session = self.get_session(session_id) valid_states = [ SessionStatus.CREATED.value, SessionStatus.ACTIVE.value ] if session['state'] not in valid_states: raise IllegalSessionStateException( "Only active and initialized sessions can be stopped.") db_session = RumbaSession.objects(id=session_id).first() if session['state'] == SessionStatus.ACTIVE.value: LOGGER.info("Stopping audio recording.") AudioManager.get_instance().stop_audio() db_session.update(set__state=SessionStatus.FINISHED.value) LOGGER.info("Session successfully stopped: [id={}]".format(session_id))
def initialize_session(self, session_id): """ Initialize a created session. A session can only be initialized from the "Created" state. When a session is initialized, it starts to record the audio and its state is modified to "Active" state. :param session_id: Session to be created :raises: - IllegalSessionStateException, if the session is no in the "Created" state. - NotExistingResource, if there's no session with such id. """ LOGGER.info("Initializing session. [session_id={}]".format(session_id)) GenericValidator.validate_id(session_id) session = RumbaSession.objects(id=session_id).first() if session is None: raise NotExistingResource("There's no session with such id.") if session['state'] != SessionStatus.CREATED.value: raise IllegalSessionStateException( "Session can only be initialized from 'Created' state") LOGGER.debug("Initializing audio record.") initial_timestmap = AudioManager.get_instance().record_audio( session['folder_url']) try: LOGGER.debug("Updating session state.") session.update(set__state=SessionStatus.ACTIVE.value, set__audio_timestamp=str(initial_timestmap)) except Exception as ex: LOGGER.exception( "Could not update session state. Stopping audio recording...") AudioManager.get_instance().stop_audio() raise ex
def record_audio(): LOGGER.info("Received request for recording microphone.") session_path = "/tmp/" timestamp = AudioManager.get_instance().record_audio(session_path) print("timestamp") print(timestamp) return jsonify({"timestamp" : str(timestamp)}), 204
def get_audio_init_ts(session_id): """ HTTP Endpoint for retrieving the initial timestamp of the audio of a session. :param session_id: Id of the rumba session. :return: - HTTP 200, with the initial timestamp in the body response. - HTTP 400, if the given id is not valid. - HTTP 404, if there's session with such id. """ LOGGER.info( "Received request for getting the initial timestamp of the session audio. [session_id={}]" .format(session_id)) try: ts = AudioManager.get_instance().get_audio_init_ts(session_id) LOGGER.info("Getting initial timestamp request succesfully finished") return jsonify({"timestmap": ts}) except ValueError as ve: LOGGER.exception( "Getting initial timestamp of audio request finished with errors: " ) raise BadRequest(ve) except NotExistingResource as ne: LOGGER.exception( "Getting initial timestamp of audio request finished with errors: " ) raise NotFound(ne)
def merge_user_video(self, video_id): """ Given the id of a video recorded by a user, it merges the video identified with such id with the audio of the session. A video can only be merged with the session audio if the record proces of the video is already finished. :param video_id: Id of the video. """ GenericValidator.validate_id(video_id) video = Video.objects(id=video_id).first() if video is None: raise NotExistingResource("There's no video with such id.") video_init_ts = VideoEditorHelper.get_initial_ts(video_id=video_id) original_video = "{}/dasher-output/video.mp4".format( video['video_path']) t_video_length = VideoLengthThread(video_file=original_video) t_video_length.start() t_video_length.join() if (t_video_length.code != 0): raise Exception("Error merging audio and video of the user.") audio_path = AudioManager.cut_audio_for_user_video( session_id=str(video['session']['id']), video_id=video_id, video_init_ts=video_init_ts, video_length=t_video_length.output) output_file = "{}/dasher-output/video-mixed.mp4".format( video['video_path']) mixer = AudioVideoMixerThread(video_file=original_video, audio_file=audio_path, output_file=output_file) mixer.start() mixer.join() if mixer.code != 0: raise Exception( "Error merging user video with audio. FFmpeg command failed.") video.update(set__mixed=True) video.update(set__mixed_video_path=output_file)
def stop_audio(): LOGGER.info("Received request for stoping microphone.") AudioManager.get_instance().stop_audio() return "", 204