gcanat / video_reader-rs

A library to fastly decode video with ffmpeg and rust
MIT License
27 stars 4 forks source link

Crash and imprecise fps report #28

Closed cryonox closed 6 days ago

cryonox commented 1 week ago

Video is here https://drive.google.com/file/d/1xhRuh7S_2n04BLXoSdPeYNO5DuAtUk9E/view?usp=sharing . The video might not have been "properly" created, it's done by merging two videos using ffmpeg concat demuxer without re-encode and probably is variable fps. But the library should not crash and gives same result as decord.

code:


import video_reader as vr
filename = 'police_protestor.mp4'
info_dict = vr.get_info(filename)
print(info_dict)
frames = vr.get_batch(filename,[0,3,4975 ],with_fallback=True)
print('ok!')
frames = vr.get_batch(filename,[4760,4808,4856],with_fallback=True) #crash
print('ok!')
frames = vr.get_batch(filename,[4760,4808,4856]) #crash
print('ok!')

Crash with

image

A few things I would like to complain in addition to the crash:

Decord code for the same video works.


from decord import VideoReader, cpu
import decord
decord.bridge.set_bridge("native")
filename = 'police_protestor.mp4'
vr = VideoReader(filename, ctx=cpu(0))
print(vr.get_avg_fps())
frames = vr.get_batch([0,3,4975]).asnumpy()
frames = vr.get_batch([4760,4808,4856]).asnumpy()
gcanat commented 1 week ago

Hello, I will have a look, thank you.

gcanat commented 1 week ago

I've pushed some changes to address the issue with fps. It should now report the correct average fps. For now you need to wrap the result in float(), ie float(info_dict["fps"]). I also fixed the issue with frames not being correctly retrieved. It should not crash anymore.

As for having a class structure similar to decord.VideoReader, I will see if I can work it out, but it is not trivial to implement. Will require more work.

cryonox commented 1 week ago

Great! It works now. Will update once I run into more problems while trying to move away from decord.

gcanat commented 1 week ago

Well, turns out it was not as hard as expected. So you can test with latest version if you want.

from video_reader import PyVideoReader

vr = PyVideoReader(filename)
indices = [12, 50, 32]
frames = vr.get_batch(indices)
cryonox commented 6 days ago

hmm...this new one changes the behaviour of previous function style. if it's not intended, maybe need more fixing? although the panic should definitely be fixed.


from video_reader import PyVideoReader

filename = 'samples/vos/police_protestor.mp4'
vr = PyVideoReader(filename)

info_dict = vr.get_info()
print(info_dict)
frames = vr.get_batch([0,3,4975 ],with_fallback=True)
frames = vr.get_batch([0,3,4975 ])
#frames = vr.decode_fast(start_frame=4760,end_frame=4975) # panic!
print('ok!')
frames = vr.get_batch([4760,4808,4856],with_fallback=True) 
print('ok!')
try:
    frames = vr.get_batch([4760,4808,4856])# error, but catchable
except:
    pass
print('ok!')
gcanat commented 6 days ago

Interesting. Will look. :+1:

gcanat commented 6 days ago

Should be fixed in v0.2.1

cryonox commented 6 days ago

fixed.