def GenerateThumbnailBytes( path, target_resolution, mime, duration, num_frames, percentage_in = 35 ): if mime in ( HC.IMAGE_JPEG, HC.IMAGE_PNG, HC.IMAGE_GIF, HC.IMAGE_WEBP, HC.IMAGE_TIFF, HC.IMAGE_ICON ): # not apng atm thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( path, target_resolution, mime ) else: if mime == HC.APPLICATION_FLASH: ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: HydrusFlashHandling.RenderPageToFile( path, temp_path, 1 ) thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( temp_path, target_resolution, mime ) except: thumb_path = os.path.join( HC.STATIC_DIR, 'flash.png' ) thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( thumb_path, target_resolution, mime ) finally: HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) else: renderer = HydrusVideoHandling.VideoRendererFFMPEG( path, mime, duration, num_frames, target_resolution ) renderer.read_frame() # this initialises the renderer and loads the first frame as a fallback desired_thumb_frame = int( ( percentage_in / 100.0 ) * num_frames ) renderer.set_position( desired_thumb_frame ) numpy_image = renderer.read_frame() if numpy_image is None: raise Exception( 'Could not create a thumbnail from that video!' ) numpy_image = HydrusImageHandling.ResizeNumPyImage( numpy_image, target_resolution ) # just in case ffmpeg doesn't deliver right thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesNumPy( numpy_image, mime ) renderer.Stop() del renderer return thumbnail_bytes
def THREADRender( self ): hash = self._media.GetHash() mime = self._media.GetMime() duration = self._media.GetDuration() num_frames_in_video = self._media.GetNumFrames() client_files_manager = HG.client_controller.client_files_manager time.sleep( 0.00001 ) if self._media.GetMime() == HC.IMAGE_GIF: ( self._durations, self._times_to_play_gif ) = HydrusImageHandling.GetGIFFrameDurations( self._path ) self._renderer = ClientVideoHandling.GIFRenderer( self._path, num_frames_in_video, self._target_resolution ) else: self._renderer = HydrusVideoHandling.VideoRendererFFMPEG( self._path, mime, duration, num_frames_in_video, self._target_resolution ) # give ui a chance to draw a blank frame rather than hard-charge right into CPUland time.sleep( 0.00001 ) self.GetReadyForFrame( self._init_position ) with self._lock: self._initialised = True while True: if self._stop or HG.view_shutdown: self._renderer.Stop() self._renderer = None with self._lock: self._frames = {} return # with self._lock: # lets see if we should move the renderer to a new position next_render_is_out_of_buffer = FrameIndexOutOfRange( self._next_render_index, self._buffer_start_index, self._buffer_end_index ) buffer_not_fully_rendered = self._last_index_rendered != self._buffer_end_index currently_rendering_out_of_buffer = next_render_is_out_of_buffer and buffer_not_fully_rendered will_render_ideal_frame_soon = self._IndexInRange( self._next_render_index, self._buffer_start_index, self._ideal_next_frame ) need_ideal_next_frame = not self._HasFrame( self._ideal_next_frame ) will_not_get_to_ideal_frame = need_ideal_next_frame and not will_render_ideal_frame_soon if currently_rendering_out_of_buffer or will_not_get_to_ideal_frame: # we cannot get to the ideal next frame, so we need to rewind/reposition self._renderer.set_position( self._buffer_start_index ) self._last_index_rendered = -1 self._next_render_index = self._buffer_start_index # need_to_render = self._last_index_rendered != self._buffer_end_index if need_to_render: with self._lock: self._rendered_first_frame = True frame_index = self._next_render_index # keep this before the get call, as it increments in a clock arithmetic way afterwards renderer = self._renderer try: numpy_image = renderer.read_frame() except Exception as e: HydrusData.ShowException( e ) return finally: with self._lock: self._last_index_rendered = frame_index self._next_render_index = ( self._next_render_index + 1 ) % num_frames_in_video with self._lock: if self._next_render_index == 0 and self._buffer_end_index != num_frames_in_video - 1: # we need to rewind renderer self._renderer.set_position( 0 ) self._last_index_rendered = -1 should_save_frame = not self._HasFrame( frame_index ) if should_save_frame: frame = GenerateHydrusBitmapFromNumPyImage( numpy_image, compressed = False ) with self._lock: self._frames[ frame_index ] = frame self._MaintainBuffer() with self._lock: work_still_to_do = self._last_index_rendered != self._buffer_end_index if work_still_to_do: time.sleep( 0.0001 ) else: half_a_frame = ( self._average_frame_duration / 1000.0 ) * 0.5 sleep_duration = min( 0.1, half_a_frame ) # for 10s-long 3-frame gifs, wew time.sleep( sleep_duration ) # just so we don't spam cpu else: self._render_event.wait( 1 ) self._render_event.clear()
def GenerateThumbnailBytes(path, target_resolution, mime, duration, num_frames, percentage_in=35): if mime in (HC.IMAGE_JPEG, HC.IMAGE_PNG, HC.IMAGE_GIF, HC.IMAGE_WEBP, HC.IMAGE_TIFF, HC.IMAGE_ICON): # not apng atm thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( path, target_resolution, mime) elif mime in [HC.APPLICATION_ZIP]: temp_dir_path = HydrusPaths.GetTempDir() try: cmd = ["unzip", path, '-d', temp_dir_path] subprocess.call(cmd) cover = sorted(list(Path(temp_dir_path).rglob("*.jpg")) + list(Path(temp_dir_path).rglob("*.png")), key=lambda p: p.name)[0].as_posix() thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( cover, target_resolution, mime) except Exception as e: thumb_path = os.path.join(HC.STATIC_DIR, 'zip.png') thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( thumb_path, target_resolution, mime) elif mime in [HC.APPLICATION_RAR]: temp_dir_path = HydrusPaths.GetTempDir() try: cmd = ["unrar", 'x', path, temp_dir_path] subprocess.call(cmd) cover = sorted(list(Path(temp_dir_path).rglob("*.jpg")) + list(Path(temp_dir_path).rglob("*.png")), key=lambda p: p.name)[0].as_posix() thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( cover, target_resolution, mime) except Exception as e: thumb_path = os.path.join(HC.STATIC_DIR, 'rar.png') thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( thumb_path, target_resolution, mime) else: if mime == HC.APPLICATION_FLASH: (os_file_handle, temp_path) = HydrusPaths.GetTempPath() try: HydrusFlashHandling.RenderPageToFile(path, temp_path, 1) thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( temp_path, target_resolution, mime) except: thumb_path = os.path.join(HC.STATIC_DIR, 'flash.png') thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( thumb_path, target_resolution, mime) finally: HydrusPaths.CleanUpTempPath(os_file_handle, temp_path) else: renderer = HydrusVideoHandling.VideoRendererFFMPEG( path, mime, duration, num_frames, target_resolution) renderer.read_frame( ) # this initialises the renderer and loads the first frame as a fallback desired_thumb_frame = int((percentage_in / 100.0) * num_frames) renderer.set_position(desired_thumb_frame) numpy_image = renderer.read_frame() if numpy_image is None: raise Exception( 'Could not create a thumbnail from that video!') numpy_image = HydrusImageHandling.ResizeNumPyImage( numpy_image, target_resolution) # just in case ffmpeg doesn't deliver right thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesNumPy( numpy_image, mime) renderer.Stop() del renderer return thumbnail_bytes