Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include napari version information in output video metadata #167

Merged
merged 8 commits into from
May 1, 2023

Conversation

GenevieveBuckley
Copy link
Contributor

@GenevieveBuckley GenevieveBuckley commented Apr 20, 2023

Description

Companion to PR napari/napari#5494

This adds a digital watermark to the video files output by napari-animation. That means in the future it may be possible to scrape publications & supplementary data, eg: like this analysis done for matplotlib https://github.com/mrocklin/arxiv-matplotlib

Try it out!

Now, you can run the examples to create a video file:

python napari-animation/examples/animate2d.py

...and then look at the metadata embedded in the video file header with ffmpeg. This ffmpeg command writes the metadata to a text file:

!ffmpeg -i demo2d.mov -f ffmetadata FFMETADATAFILE.txt

And when you look at the output

cat FFMETADATAFILE.txt

...you see something like this (note the new "title" metadata field, which was not there before:

;FFMETADATA1
major_brand=qt  
minor_version=512
compatible_brands=qt  
title="napari version 0.4.17 https://napari.org/"
encoder=Lavf59.27.100

Actually, here is a simpler way to read the metadata from the video file:

    # Read metadata back in, and check for napari version information
    # We expect to see a metadata line in the metadata like this:
    # title="napari version 0.4.17 https://napari.org/"
    with open(output_video_filename, 'rb') as f:
        content = f.read()
    assert b"napari version" in content
    assert b"https://napari.org" in content

Additional details

I have stuffed the napari version information into the "title" metadata key, because that seems to be the most widely available. (.mp4 files do allow a "description" metadata field, but that is not supported by .avi, .mov, and possibly many other file formats).

@codecov
Copy link

codecov bot commented Apr 20, 2023

Codecov Report

Merging #167 (3ad70f0) into main (d8bd609) will increase coverage by 0.90%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main     #167      +/-   ##
==========================================
+ Coverage   85.31%   86.22%   +0.90%     
==========================================
  Files          24       26       +2     
  Lines         926      987      +61     
==========================================
+ Hits          790      851      +61     
  Misses        136      136              
Impacted Files Coverage Δ
napari_animation/_tests/test_animation.py 100.00% <100.00%> (ø)
napari_animation/animation.py 87.25% <100.00%> (+0.38%) ⬆️

... and 3 files with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@GenevieveBuckley GenevieveBuckley changed the title WIP: animation metadata including napari version Include napari version information in output video metadata Apr 20, 2023
"""Test output video file contians napari version metadata()"""
animation = animation_with_key_frames
output_filename = tmp_path / f"test{ext}"
animation.animate(output_filename)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice that the other tests (like test_animate_filenames above) are very careful to mock/patch the video writer, so I'm not sure if you won't like that it actually runs here.
I'm not really sure how best to test this without generating real output video files though.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is okay, that was done because the output wasn't being checked for anything afaik

@GenevieveBuckley
Copy link
Contributor Author

GenevieveBuckley commented Apr 20, 2023

Link to a notebook I used while I was figuring this out: https://gist.github.com/GenevieveBuckley/72e438539ab03c792d52040ccb9e8f02

The trick was, you need to SEPARATE the "-metadata" string from the "title=MyTitle" string in the output_params list that gets passed in to imageio_ffmpeg.

        output_params = ["-metadata", f'title="{description}"']

It will NOT work if you pass it all as one string, eg: output_params=["-metadata title=MyTitle"]

Plus, you just extend the idea if you want to pass in more metadata keys. The only problem is, not many metadata keys are supported by a wide variety of file formats.

output_params = [
    "-metadata", f'title="My Title"',
    "-metadata", f'description="Description goes here"',  # description metadata supported by .mp4, but not .mov, .avi, and possibly many other file formats
]

Copy link
Collaborator

@alisterburt alisterburt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! thanks for the PR - made a tiny change so there wasnt a spurious reference to __version__ within the package but otherwise this is great!

"""Test output video file contians napari version metadata()"""
animation = animation_with_key_frames
output_filename = tmp_path / f"test{ext}"
animation.animate(output_filename)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is okay, that was done because the output wasn't being checked for anything afaik

napari_animation/animation.py Outdated Show resolved Hide resolved
napari_animation/animation.py Outdated Show resolved Hide resolved
@GenevieveBuckley
Copy link
Contributor Author

Thanks for the review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants