mp4 - #15
Conversation
Since upstream is very stable, this is a full copy rather than a submodule.
The integer period was causing issues with 60 fps labels. Despite microsecond resolution, rendered timecodes were visibly drifting (because the period 1e6 / 60 is not a round number). This commit replaces it with a floating-point frequency. The timecodes are computed where relevant with round(1 / frequency * index).
For the sake of completeness, will probably be refactored soon.
I had to fix __init__.py after running isort (there may be a bug in the last version)
There was a problem hiding this comment.
An absolutely incredible effort. I can really see how much time and effort you spent here. It shows, and the API that's emerging from this is gorgeous. Not to mention really, really useful.
My only puzzle is whether we can somehow avoid copying in all the x264 code. Isn't there some for of cross-platform library for this? I realize this will be an added dependency, but it is a dependency, and then we don't have to maintain it :-)
Apart from that, I have a few minor remarks about the code. (But in general, I think you made some great choices. Particularly around the naming for the parameters (we discussed frequency etc). There are so many changes that it's difficult to make it through all of them, I'm not well-versed in Rust, and I skipped the x264 code. But all in all, I think it's ready to go! I can't wait to get my hands on this :)
Oh, and regarding the cross-compilation, I'm definitely in favor of waiting for a one-size-fits-all solution. That is, wait for the ARM runners. Especially if it means simplifying our lives. Our time is limited, unfortunately.
| file_type = enums.video_file_type_guess(path) | ||
| else: | ||
| file_type = enums.validate_video_file_type(file_type) | ||
| state_manager = frame_stream.StateManager(stream=stream, on_progress=on_progress) |
There was a problem hiding this comment.
Isn't the state manager redundant here? Maybe we could consider a default argument
There was a problem hiding this comment.
I am not sure what you mean by redundant.
There was a problem hiding this comment.
You're passing in the on_progress as an empty lambda (lambda _: None). Doesn't that mean the state manager is redundant? Or that the state isn't being updated?
There was a problem hiding this comment.
Oh, I see! The state manager is indeed redundant if the user does not specify an on_progress function, but it is useful if they do. We could optimize out the state manager when on_progress does nothing (we would probably want to use None as a default to do that), but it (hopefully) has minimal impact on performance (I have not checked though).
| SPEED_UP_PRECISION: float = 1e-3 | ||
|
|
||
|
|
||
| def number_to_string(number: typing.Union[int, float], precision: float) -> str: |
There was a problem hiding this comment.
Why can't we use format strings for this? Like f"{number:.2f}". It seems like you're trying to avoid some floating point rounding nastiness
There was a problem hiding this comment.
I added this to show integers when possible.
The function is intended to format the "speed up" ratio that appears on videos (that is, the duration represented by one event frame divided by the time that the frame is shown on screen by the video player). I quite like the following display rules:
- Show the speed up directly when it is larger than one (for instance
x 10for a time-lapse where each event frame covers 1/6 seconds in a video where each frame is shown for 1/60 seconds). - Show the speed up as an inverse when it is smaller than one (for instance
x 1/10for a slow-motion video where each event frame covers 1/600 seconds in a video where each frame is shown for 1/60 seconds). This is particularly useful when discussing very slow motion videos ("ten thousand times slower than real-time", represented byx 1/10000, is easier to parse thanx 0.0001). - Show integers when close to a round value (
x 1/10instead ofx 1/10.00) but keep the fractional digits where needed (x 1/1.4, notx 1/1).
Python's formatting function gives us three options that all are all (sometimes) problematic:
- Let Python pick the number of digits (
f"x {number}"), which can cause problems when the number is close to but not quite an integer. - Always show an integer (
f"x {number:.0f}"), which can be misleading when the number is a small non-integer. - Always show digits (
f"x {number:.2f}"), which often shows redundant fractional digits.
There was a problem hiding this comment.
There are also https://docs.python.org/3/library/stdtypes.html#float.as_integer_ratio and https://docs.python.org/3/library/fractions.html#fractions.Fraction. I agree that the use cases are great, but I'm just wondering whether some of the code could be simplified. It seems like a problem that someone in the Python ecosystem has faced before :)
There was a problem hiding this comment.
That's a fair point! I was not aware of as_integer_ratio. I'll try to refactor this to simplify the code.
|
Hi @Jegp, Thank you for the review, this is extremely helpful! Regarding H.264 video compression, there are indeed a few ways to set it up.
I would love to migrate to (c) when a mature library shows up. In the mean time, I am leaning towards (a) since debugging CI/CD issues, as frustrating as it is, is still better than debugging compatibility issues on a wide range of operating systems and configurations (https://xkcd.com/1987/). |
|
Thank you for your comments. I agree that (c) is by far the best option. But I also agree that we need the library to exist. I also agree that (a) is the best solution for now. I just don't like it :) At some point, I would really like to leverage nix to sort out these kinds of dependencies. Because then we can link all we want. Statically and dynamically. Unfortunately, it only works on Windows subsystem at the moment (https://nix.dev/install-nix.html) |
|
🎉 |
After a somewhat lengthy process (it took 70 attempts), x264 finally compiles on all platforms!
Besides video generation, this PR also includes the addition of an optional terminal progress bar.
There is no cross-compilation at the moment (we compile macOS ARM wheels on an ARM runner, macOS intel wheels on an intel runner, and Windows and Linux wheels on intel runners). This means that we do not create wheels for Windows ARM or Linux ARM (for instance the Raspberry Pi) at the moment. There are two ways to address this: