# Opencv-python video capture set method not working as expected

**URL:** <https://forum.opencv.org/t/opencv-python-video-capture-set-method-not-working-as-expected/12727>\
**Category:** Python\
**Tags:** ffmpeg, videoio\
**Created:** [April 8, 2023, 8:36am UTC](https://forum.opencv.org/t/opencv-python-video-capture-set-method-not-working-as-expected/12727 "2023-04-08T08:36:19Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tamiri](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/tamiri/32/7623_2.png) [@tamiri](https://forum.opencv.org/u/tamiri)\
**Post date:** [April 8, 2023, 8:36am UTC](https://forum.opencv.org/t/opencv-python-video-capture-set-method-not-working-as-expected/12727/1 "2023-04-08T08:36:19Z")

</div>

Hi,  
im using opencv-python package, and got a wierd issue when using videocapture.set(cv2.CAP\_PROP\_POS\_MSEC, value).  
After using the set method, and then the get method, the returned value is completely different.  
This is a project that works as expected in a mac laptop (including when using the same video file), but when i try running it on PopOs it dosent work as expected.  
The video file is of length of 90+ minutes, so the new time im trying to set is definitely a valid one.

OS: Pop!\_OS 22.04 LTS  
CPU: 12th Gen Intel® Core™ i7-12650H  
GPU: GeForce RTX 3070 Mobile  
Python: 3.10.6  
ffmpeg: 4.4.2-0ubuntu0.22.04.1  
opencv-python: 4.7.0.72

Code (just the relevant part):  
current\_millis = cap.get(cv2.CAP\_PROP\_POS\_MSEC)  
# current\_millis=211631.6666666667  
# skip\_seconds=24  
skip\_to\_millis=cap.get(cv2.CAP\_PROP\_POS\_MSEC) + (  
skip\_seconds\* 1000)  
# skip\_to\_millis =235631.6666666667  
cap.set(cv2.CAP\_PROP\_POS\_MSEC,  
skip\_to\_millis)  
current\_millis = cap.get(cv2.CAP\_PROP\_POS\_MSEC)  
# current\_millis=2618.1222222222223

Any help will be appreciated!

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [April 8, 2023, 1:37pm UTC](https://forum.opencv.org/t/opencv-python-video-capture-set-method-not-working-as-expected/12727/2 "2023-04-08T13:37:23Z")

</div>

> <https://github.com/opencv/opencv/issues/23088>
>
> This code wasn't touched in a long time. I don't know if there are tests for it.…
> 
> https://github.com/opencv/opencv/blob/9208dcb07c015e1fda44e40bb07b43c700b4bf46/modules/videoio/src/cap\_ffmpeg\_impl.hpp#L1957-L1978
> 
> I just noticed some inconsistencies in seeking that might be caused by this.
> 
> 1. the \`seek()\` call has overloads for \`double\` (seconds) and \`int64\_t\` (frame number) but in the POS\_AVI\_RATIO case it's called like it took a timestamp (in timebase)
> 2. the \`picture\_pts\` value is set wrong \_all\_ cases
> 
> Test video, 23.976 fps, about 10 seconds, specifics not important):
> 
> \`$ ffmpeg -f lavfi -i testsrc=duration=10:size=320x100:rate=24000/1001:decimals=3 -c:v libx264 -b:v 1M -y testsrc.mov\`
> 
> Test script:
> \`\`\`python
> import cv2 as cv
> 
> vid = cv.VideoCapture("testsrc.mov", apiPreference=cv.CAP\_FFMPEG)
> assert vid.isOpened()
> 
> print("seek: frame 0")
> vid.set(cv.CAP\_PROP\_POS\_FRAMES, 0)
> print("at:", vid.get(cv.CAP\_PROP\_POS\_FRAMES), "frames,", vid.get(cv.CAP\_PROP\_POS\_MSEC), "msec")
> 
> for k in range(5):
> (rv, frame) = vid.read()
> assert rv
> print("read")
> #imshow(frame)
> print("at:", vid.get(cv.CAP\_PROP\_POS\_FRAMES), "frames,", vid.get(cv.CAP\_PROP\_POS\_MSEC), "msec")
> 
> print("seek: frame 3")
> vid.set(cv.CAP\_PROP\_POS\_FRAMES, 3)
> \#print("seel: msec 130")
> \#vid.set(cv.CAP\_PROP\_POS\_MSEC, 130)
> print("at:", vid.get(cv.CAP\_PROP\_POS\_FRAMES), "frames,", vid.get(cv.CAP\_PROP\_POS\_MSEC), "msec")
> 
> for k in range(5):
> (rv, frame) = vid.read()
> assert rv
> #print("read")
> #imshow(frame)
> print("at:", vid.get(cv.CAP\_PROP\_POS\_FRAMES), "frames,", vid.get(cv.CAP\_PROP\_POS\_MSEC), "msec")
> \`\`\`
> 
> That emits this:
> \`\`\`
> seek: frame 0
> at: 0.0 frames, 0.0 msec
> at: 1.0 frames, 0.0 msec
> at: 2.0 frames, 41.708333333333336 msec
> at: 3.0 frames, 83.41666666666667 msec
> at: 4.0 frames, 125.12499999999999 msec
> at: 5.0 frames, 166.83333333333334 msec
> seek: frame 3
> at: 3.0 frames, 0.125 msec ### NOTICE HERE
> at: 4.0 frames, 125.12499999999999 msec
> at: 5.0 frames, 166.83333333333334 msec
> at: 6.0 frames, 208.54166666666666 msec
> at: 7.0 frames, 250.24999999999997 msec
> at: 8.0 frames, 291.9583333333333 msec
> \`\`\`
> 
> As you can see in the implementation of \`CvCapture\_FFMPEG::setProperty()\`, seeking with \`CAP\_PROP\_POS\_FRAMES\` puts the frame number into \`picture\_pts\`, instead of an actual timestamp. This plain number is then interpreted as a timestamp (using timebase \`1001/24000\`), which results in \`get(CAP\_PROP\_POS\_MSEC)\` reporting a number that's clearly off (uses \`dts\_to\_sec(picture\_pts) \* 1000\`, sensible). The following read() fixes that up though because seeking succeeded and \`picture\_pts\` is just a "cached" value.
> 
> Seeking with \`CAP\_PROP\_POS\_MSEC\` is similarly broken.
> 
> Some calculations, comparing actual timestamps and frame numbers interpreted as timestamps:
> \`\`\`
> TB = 1/24000 # same as vid.get(cv.CAP\_PROP\_POS\_AVI\_RATIO)
> \# one frame of time is an increment of 1001 ticks
> dts\_to\_sec = lambda ts: ts \* TB
> dts\_to\_sec(3003) \* 1000 # 125.12499999999999
> dts\_to\_sec(3120) \* 1000 # 130
> dts\_to\_sec(7007) \* 1000 # 291.9583333333333
> \# seek(POS\_FRAMES, 3)
> dts\_to\_sec(3) \* 1000 # 0.125
> \# seek(POS\_MSEC, 130)
> dts\_to\_sec(130) \* 1000 # 5.416666666666667
> \`\`\`
> 
> I should mention the \`CAP\_PROP\_POS\_AVI\_RATIO\` is a complete mess too. \`get()\` returns the timebase (useful if we could seek using timestamps), set() calculates a timestamp from a 0..1 float and the video's total duration (in timebase), so that doesn't match up at all. If you think that warrants discussion, I could open a separate issue for that.
> 
> I haven't given this enough of a look to propose a patch yet. I'd like some opinions on this, some guidance on design decisions that need to be made and documented in the course of fixing this. The AVI\_RATIO stuff needs to be brought in line with what the docs state (value range 0 to 1). I'm inclined to introduce \`CAP\_PROP\_TIMEBASE\` and \`CAP\_PROP\_POS\_TIMESTAMP\` just for completeness/passthrough but that wouldn't necessarily map cleanly onto backends besides FFMPEG.
> 
> I am planning to propose a separate patch that would let me seek \*quickly\*, bypassing the frame-accurate positioning that happens in \`CvCapture\_FFMPEG::seek\` (code after \`avcodec\_flush\_buffers\` call). I have some use cases that would greatly benefit from quick seeking and then querying the actual achieved position/timestamp.

I don’t know if they ignore me automatically or manually, or they’re _that_ backlogged, but they haven’t even triaged the issue yet (slapped appropriate labels on it)

---

<div class="post-metadata">

**Author:** ![tamiri](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/tamiri/32/7623_2.png) [@tamiri](https://forum.opencv.org/u/tamiri)\
**Post date:** [April 8, 2023, 6:29pm UTC](https://forum.opencv.org/t/opencv-python-video-capture-set-method-not-working-as-expected/12727/3 "2023-04-08T18:29:54Z")

</div>

Thanks for the comment.  
I opened another issue, hopefully someone will pick it up.  
You think its something we can fix on our own?

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [April 8, 2023, 9:28pm UTC](https://forum.opencv.org/t/opencv-python-video-capture-set-method-not-working-as-expected/12727/4 "2023-04-08T21:28:28Z")

</div>

looks fairly easy to do, from what I remember of my investigation of the code. all the ffmpeg stuff is in that file.

just search and highlight a few of the variables relating to `picture_pts`

there are multiple issues in there, separate but related. it’s not going to be a single-line fix.

---

<div class="post-metadata">

**Author:** ![tamiri](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/tamiri/32/7623_2.png) [@tamiri](https://forum.opencv.org/u/tamiri)\
**Post date:** [April 10, 2023, 10:51pm UTC](https://forum.opencv.org/t/opencv-python-video-capture-set-method-not-working-as-expected/12727/5 "2023-04-10T22:51:52Z")

</div>

@crackwitz got a response from one of the moderators, and provided additional information they requested.  
This is the issue: [video capture .set() method not working as expected · Issue #23472 · opencv/opencv · GitHub](https://github.com/opencv/opencv/issues/23472)
