-
Notifications
You must be signed in to change notification settings - Fork 420
Closed
Description
Overview
- I want to traverse a video and after frame 10 - add 10 more frames made from current 10-nth frame onto which I draw an overlay and then resume and remux the rest of the frames.
- I don't know how to compute pts for new added frames and the rest
I am using the example provided by @jlaine at #473 with great help to know how to compute pts.
I've came with this formula hardly digging
def frame_to_pts(frame, time_base, frame_rate, start_time):
return int((frame + start_time * time_base * frame_rate) / (time_base * frame_rate))then
import av
import cv2
# open input and find video stream
input_container = av.open('input.mp4', 'r')
input_stream = input_container.streams.get(video=0)[0]
# open output and add a video stream
output_container = av.open('output.mp4', 'w')
output_stream = output_container.add_stream('h264', rate=input_stream.rate)
frame_current = 0
for frame in input_container.decode(input_stream):
# perform edge detection
img = frame.to_ndarray(format='bgr24')
img = cv2.cvtColor(cv2.Canny(img, 100, 200), cv2.COLOR_GRAY2BGR)
if frame_current > 10 and frame_current <= 20:
# add 10 more frames
for i in range(10):
# compute new pts
pts_computed = frame_to_pts(frame_current, frame.time_base, input_stream.average_rate, input_stream.start_time)
# rebuild a VideoFrame, preserving timing information
new_frame = av.VideoFrame.from_ndarray(img, format='bgr24')
new_frame.pts = pts_computed
new_frame.time_base = frame.time_base
# encode and mux
for packet in output_stream.encode(new_frame):
output_container.mux(packet)
# advance one frame
frame_current += 1
else:
# compute new pts
pts_computed = frame_to_pts(frame_current, frame.time_base, input_stream.average_rate, input_stream.start_time)
# rebuild a VideoFrame, preserving timing information
old_frame = av.VideoFrame.from_ndarray(img, format='bgr24')
old_frame.pts = pts_computed
old_frame.time_base = frame.time_base
# encode and mux
for packet in output_stream.encode(old_frame):
output_container.mux(packet)
# advance one frame
frame_current += 1
# flush and close output
for packet in output_stream.encode(None):
output_container.mux(packet)
output_container.close()Expected behavior
The formula above seems to work for h264 codec, but I have no confidence in it -
Actual behavior
Switching to h264_nvenc instead of h264 gets me pts < dts errors.
Investigation
Tried other codecs hevc_nvenc - seems to work
Research
I have done the following:
- Checked the PyAV documentation
- Searched on Google
- Searched on Stack Overflow
- Looked through old GitHub issues
- Asked on PyAV Gitter
- ... and waited 72 hours for a response.
Metadata
Metadata
Assignees
Labels
No labels