Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

How do I load and store an mp4 video file? #1069

Closed
4 of 6 tasks
anna-charlotte opened this issue Jan 4, 2023 · 0 comments
Closed
4 of 6 tasks

How do I load and store an mp4 video file? #1069

anna-charlotte opened this issue Jan 4, 2023 · 0 comments

Comments

@anna-charlotte
Copy link

anna-charlotte commented Jan 4, 2023

Overview

I want to have two functions:

  • one to load a video array from an .mp4 file
  • to store a video array to an .mp4 file

I tried implementing those as follows:

from ctypes import Union
from pathlib import Path
from typing import BinaryIO

import av
import numpy as np


def load(file_path, **kwargs) -> np.ndarray:
    frames = []
    with av.open(file_path, **kwargs) as container:
        for i, frame in enumerate(container.decode(video=0)):
            img = frame.to_image()
            frames.append(img)

    return np.moveaxis(np.stack(frames), -3, -2)


# following this approach: https://github.com/PyAV-Org/PyAV/issues/498
def save_to_file(
    np_tensor: np.ndarray,
    file_path: str,
    frame_rate: int = 30,
    codec: str = 'mpeg4',
) -> None:

    video_tensor = np.moveaxis(np.clip(np_tensor, 0, 255), -3, -2).astype('uint8')

    with av.open(file_path, mode='w') as container:
        if video_tensor.ndim == 3:
            video_tensor = np.expand_dims(video_tensor, axis=0)

        stream = container.add_stream(codec, rate=frame_rate)
        stream.width = video_tensor.shape[-2]
        stream.height = video_tensor.shape[-3]
        stream.pix_fmt = 'yuv420p'

        for vid in video_tensor:
            frame = av.VideoFrame.from_ndarray(vid, format="rgb24")
            frame.pts = None

            for packet in stream.encode(frame):
                container.mux(packet)

        for packet in stream.encode(None):
            container.mux(packet)


tmp_file = str(Path.cwd() / 'tmp.mp4')

video_tensor = np.array(
    [[
        [[1, 2, 3], [4, 5, 6]],
        [[7, 8, 9], [10, 11, 12]],
        [[13, 14, 15], [16, 17, 18]],
        [[19, 20, 21], [22, 23, 24]],
    ]]
)


save_to_file(np_tensor=video_tensor, file_path=tmp_file)

video_from_file = load(tmp_file)
assert video_tensor.shape == video_from_file.shape
print(f"tensor = {video_tensor}")
print(f"video_from_file = {video_from_file}")
assert np.allclose(video_tensor, video_from_file)

Expected behavior

I have an mp4 file, that I want to load to video_1. When storing the video_1 array to an mp4 file, and then load the video from that new file to a second array, video_2, I expect: np.allclose(video_1, video_2)

Actual behavior

I am getting an Assertion error:

tensor = [[[[ 1  2  3]
   [ 4  5  6]]

  [[ 7  8  9]
   [10 11 12]]

  [[13 14 15]
   [16 17 18]]

  [[19 20 21]
   [22 23 24]]]]
video_from_file = [[[[ 3  4  7]
   [ 3  4  7]]

  [[ 8  9 12]
   [ 8  9 12]]

  [[15 16 19]
   [15 16 19]]

  [[20 21 24]
   [20 21 24]]]]
Traceback (most recent call last):
  File "/Users/charlottegerhaher/Library/Application Support/JetBrains/PyCharm2022.2/scratches/scratch_26.py", line 68, in <module>
    assert np.allclose(video_tensor, video_from_file)
AssertionError

Traceback:

Traceback (most recent call last):
  File "/Users/charlottegerhaher/Library/Application Support/JetBrains/PyCharm2022.2/scratches/scratch_26.py", line 68, in <module>
    assert np.allclose(video_tensor, video_from_file)
AssertionError

Research

I have done the following:

@PyAV-Org PyAV-Org locked and limited conversation to collaborators Jan 23, 2023
@jlaine jlaine converted this issue into discussion #1078 Jan 23, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant