How to guide

Create your own writers

To add custom writer, extend the Writer class implemented in Katna.writer. The writer needs to implement the write method, which receives the filepath of the input file and the data generated by the Katna Library.

Below is one example where a custom writer is created to prints data instead of writing it on disk. This example uses keyframe extraction feature:

from Katna.video import Video
from Katna.writer import Writer
import os
import ntpath

# PrintDataWriter will print the data generated by Katn alibrary
class PrintDataWriter(Writer):
"""Custom writer to print the data
"""

    def write(self, filepath, data):
    """The write method to process data generated by Katna Library
    """
        for counter, img in enumerate(data):
            print("Data for file: ", filepath, " is : ", data)


#instantiate the video class
vd = Video()

#number of key-frame images to be extracted
no_of_frames_to_return = 3

#Input Video directory path
#All .mp4 and .mov files inside this directory will be used for keyframe extraction)
videos_dir_path = os.path.join(".", "tests","data")

# initialize the print writer
printwriter = PrintDataWriter()


vd.extract_keyframes_from_videos_dir(
        no_of_frames=no_of_frames_to_return, dir_path=videos_dir_path,
        writer=printwriter
)

In this example, we have extended KeyFrameDiskWriter to change the naming convention of saved files. To do this, overwrite the generate_output_filename method. For KeyFrameDiskWriter, this method takes 2 arguments: filepath and keyframe_number. Let’s add a suffix to the filename generated in teh example:

from Katna.video import Video
from Katna.writer import KeyFrameDiskWriter
import os
import ntpath

class CustomDiskWriter(KeyFrameDiskWriter):
"""Custom disk writer to save filename differently

:param KeyFrameDiskWriter: Writer class to overwrite
:type KeyFrameDiskWriter: Writer
"""

    # This method is used to generate output filename for a keyframe
    # Here we call the super on te base class and add a suffix
    def generate_output_filename(self, filepath, keyframe_number):
        """Custom output filename method

        :param filepath: [description]
        :type filepath: [type]
        """
        filename = super().generate_output_filename(filepath, keyframe_number)

        suffix = "keyframe"

        return "_".join([filename, suffix])

Note: The similar writer approach can be used in conjuction with Katna Image module.

Compress video using Katna

Step 1

Import the video module

from Katna.video import Video

Step 2

Instantiate the video class inside your main module (necessary for multiprocessing in windows)

if __name__ == "__main__":
     vd = Video()

Step 3

Call the compress_video method. The method accepts one required parameter that is path to input file returns status whether compression was done successfully or not. Refer to API reference for further details. Below are the parameters required by the method

  1. file_path: Input video full file path. This is the only compulsory parameter
status = vd.compress_video(file_path= video_file_path)

Step 4 (Optional)

In case you play around with the different parameters like where to save compressed file etc. you can change optional parameters in compress_video function. Refer to API reference for further details. Below are the optional parameters supported by the method

1. force_overwrite (bool, optional) – optional parameter if True then if there is already a file in output file location function will overwrite it, defaults to False

2. crf_parameter (int, optional) – Constant Rate Factor Parameter for controlling amount of video compression to be applied, The range of the quantizer scale is 0-51: where 0 is lossless, 23 is default, and 51 is worst possible. It is recommend to keep this value between 20 to 30 A lower value is a higher quality, you can change default value by changing config.Video.video_compression_crf_parameter

3. output_video_codec (str, optional) – Type of video codec to choose, Currently supported options are libx264 and libx265, libx264 is default option. libx264 is more widely supported on different operating systems and platforms, libx265 uses more advanced x265 codec and results in better compression and even less output video sizes with same or better quality. Right now libx265 is not as widely compatible on older versions of MacOS and Widows by default. If wider video compatibility is your goal you should use libx264., you can change default value by changing Katna.config.Video.video_compression_codec

4. out_dir_path (str, optional) – output folder path where you want output video to be saved, defaults to “”

5. out_file_name (str, optional) – output filename, if not mentioned it will be same as input filename, defaults to “”

vd.compress_video(file_path, force_overwrite=False, \
crf_parameter=23, output_video_codec='libx264', out_dir_path='', out_file_name='')

Code below is a complete example for a single video file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  import os
  from Katna.video import Video

  def main():

       vd = Video()

       # folder to save extracted images
       output_folder_for_compressed_videos= "compressed_folder"
       out_dir_path = os.path.join(".", output_folder_for_compressed_videos)

       if not os.path.isdir(out_dir_path):
            os.mkdir(out_dir_path)

       # Video file path
       video_file_path = os.path.join(".", "tests", "data", "pos_video.mp4")
       print(f"Input video file path = {video_file_path}")

       status = vd.compress_video(
            file_path=video_file_path,
            out_dir_path=out_dir_path
       )


  if __name__ == "__main__":
       main()

Compress all videos in folder using Katna

Step 1

Import the video module

from Katna.video import Video

Step 2

Instantiate the video class inside your main module (necessary for multiprocessing in windows)

if __name__ == "__main__":
     vd = Video()

Step 3

Call the compress_videos_from_dir method. The method accepts one required parameter that is path to input folder where videos needs to be picked for compression returns status whether compression was done successfully or not. Refer to API reference for further details. Below are the parameters required by the method

  1. dir_path: Input videos full folder path. This is the only compulsory parameter
status = vd.compress_videos_from_dir(dir_path=input_video_folder_path)

Step 4 (Optional)

In case you play around with the different parameters like where to save compressed file etc. you can change optional parameters in compress_video function. Refer to API reference for further details. Below are the optional parameters supported by the method

1. force_overwrite (bool, optional) – optional parameter if True then if there is already a file in output file location function will overwrite it, defaults to False

2. crf_parameter (int, optional) – Constant Rate Factor Parameter for controlling amount of video compression to be applied, The range of the quantizer scale is 0-51: where 0 is lossless, 23 is default, and 51 is worst possible. It is recommend to keep this value between 20 to 30 A lower value is a higher quality, you can change default value by changing config.Video.video_compression_crf_parameter

3. output_video_codec (str, optional) – Type of video codec to choose, Currently supported options are libx264 and libx265, libx264 is default option. libx264 is more widely supported on different operating systems and platforms, libx265 uses more advanced x265 codec and results in better compression and even less output video sizes with same or better quality. Right now libx265 is not as widely compatible on older versions of MacOS and Widows by default. If wider video compatibility is your goal you should use libx264., you can change default value by changing Katna.config.Video.video_compression_codec

4. out_dir_path (str, optional) – output folder path where you want output video to be saved, defaults to “”

vd.compress_videos_from_dir(dir_path, force_overwrite=False, \
crf_parameter=23, output_video_codec='libx264', out_dir_path='')

Code below is a complete example for a single video file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  import os
  from Katna.video import Video

  def main():

       vd = Video()

       # folder to save extracted images
       output_folder_for_compressed_videos= "compressed_folder"
       out_dir_path = os.path.join(".", output_folder_for_compressed_videos)

       if not os.path.isdir(out_dir_path):
            os.mkdir(out_dir_path)

       # Video file path
       video_folder_path = os.path.join(".", "tests", "data")
       print(f"Input video folder path = {video_folder_path}")

       status = vd.compress_videos_from_dir(
            dir_path=video_folder_path,
            out_dir_path=out_dir_path
       )


  if __name__ == "__main__":
       main()

Crop Image using CV

You can use crop_image_from_cvimage function in case you want to crop in-memory images. This method accepts opencv image as image source. Rest of the parameters are same as crop_images method. This function helps in connecting smart image cropping to any existing workflow.

img = cv2.imread(image_file_path)

crop_list = img_module.crop_image_from_cvimage(
    input_image=img,
    crop_width,
    crop_height,
    num_of_crops,
    filters=[],
    down_sample_factor=config.Image.down_sample_factor,
)

Crop Image using aspect ratio

If you want to get the crops by a specified aspect ratio. You can use crop_image_with_aspect function. This method accepts crop_aspect_ratio as parameter instead of height & width and returns a list of crop rectangles wrt to each crop dimension it finds with the specified aspect ratio.

crop_aspect_ratio: use this parameter to specify the aspect ratio by which crops need to be extracted.The parameter expects you to specify the aspect ratio in string format eg. ‘4:3’ or ‘16:9’.

from Katna.writer import ImageCropDiskWriter
diskwriter = ImageCropDiskWriter(location="selectedcrops")

image_file_path = <Path where the image is stored>
crop_aspect_ratio = '4:3'

crop_list = img_module.crop_image_with_aspect(
    file_path=image_file_path,
    crop_aspect_ratio=<crop_aspect_ratio>,
    num_of_crops=<no_of_crops_to_return>,
    writer=diskwriter,
    filters=<filters>,
    down_sample_factor=<number_by_which_image_to_downsample>
)