awslabs / amazon-kinesis-video-streams-producer-sdk-java

Allows developers to install and customize their connected camera and other devices to securely stream video, audio, and time-encoded data to Kinesis Video Streams
Apache License 2.0
78 stars 76 forks source link

How to set 'Fragment Length' with java code #194

Closed Fabulous-maker closed 2 months ago

Fabulous-maker commented 3 months ago

I tried to upload MKV video files to KVS using the PutMedia API, but it seems that I haven't seen any parameter in PutMedia to set Fragment Length. I think PutMedia is only a API to put media to KVS Service,It cannot transfer or modify origin media data like key frame interval generating to reset or re-generate a new media data to put to kvs,right?

Gstreamer can collect media data from origin device and transfer them with some specific configuration like ‘max-keyframe-interval=20’ to control fragment Length,finally to reduce end to end latency for kvs service.

I am not sure if the above explanation is reasonable. If there are any errors, you can correct them.Thanks for your response in advance!

sirknightj commented 3 months ago

Yes, you are correct. PutMedia persists the data sent to it, it doesn't modify any of the video frames.

The producer SDK also doesn't touch the raw bytes (data) of the incoming frame data. You will need to re-encode the video frames before they are sent to the Producer SDK if you want to change the keyframe (i-frame) interval. When converting the frames sent by the H.264 encoder to KinesisVideoFrames, keyframes are denoted with they FRAME_FLAG_KEY_FRAME flag. This will denote the first frame of a new fragment.

Using GStreamer's x264enc with the key-int-max parameter, it will re-encode the frames if necessary.

If you're trying to upload pre-recorded MKV files, you can use open-source libraries like ffmpeg to re-encode your video to your desired specific keyframe interval. Note that there are certain limits for the minimum and maximum fragment duration listed on the limits page.

If you have a pre-recorded mkv file, you can inspect the i-frame interval using ffprobe:

ffprobe -select_streams v  -show_entries frame=key_frame,pkt_dts_time,pict_type -of csv input.mkv  

frame,1,1.301000,I
frame,0,1.435000,P
frame,0,1.568000,P
frame,0,1.701000,P
frame,0,1.835000,P
frame,0,1.968000,P
frame,0,2.101000,P
frame,0,2.235000,P
frame,0,2.368000,P
frame,0,2.501000,P
frame,0,2.635000,P
frame,0,2.768000,P
frame,0,2.901000,P
...

To re-encode the frames with 10 frames per fragment:

ffmpeg -i input.mkv -c:v libx264 -x264-params keyint=10:min-keyint=10 -bf 0 -c:a copy output.mkv 

Output of ffprobe:

frame,1,1.200000,I,
frame,0,1.333000,P
frame,0,1.467000,P
frame,0,1.600000,P
frame,0,1.733000,P
frame,0,1.867000,P
frame,0,2.000000,P
frame,0,2.133000,P
frame,0,2.267000,P
frame,0,2.400000,P
frame,1,2.533000,I
frame,0,2.667000,P
frame,0,2.800000,P
frame,0,2.933000,P
Fabulous-maker commented 2 months ago

Hi @sirknightj ,many thanks for your updates.I will close this issue.