diff --git a/.gitignore b/.gitignore index 00a3f93..6a3a1c5 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ docs/source/*.html *.gif *.mp4 +*.webm **/.DS_Store diff --git a/docs/source/conf.py b/docs/source/conf.py index 3488333..2843d73 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,4 +1,4 @@ -# Configuration file for the Sphinx documentation builder. +# Config file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full # list see the documentation: diff --git a/docs/source/index.ipynb b/docs/source/index.ipynb index e216b7f..dfe82b4 100644 --- a/docs/source/index.ipynb +++ b/docs/source/index.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 25, "metadata": { "collapsed": false, "jupyter": { @@ -27,25 +27,28 @@ "\n", "\n", "def display(fname):\n", - " if fname.endswith(\"gif\"):\n", + " \n", + " extension = fname.split(\".\")[-1]\n", + " \n", + " if extension == \"gif\":\n", " gif = open(fname,'rb').read() \n", " return Image(b64encode(gif),embed=True)\n", " \n", - " elif fname.endswith(\"mp4\"):\n", + " elif extension == \"mp4\" or extension == \"webm\":\n", " from IPython.display import HTML, display\n", " \n", - " mp4 = open(fname,'rb').read() \n", - " data = \"data:video/mp4;base64,\" + b64encode(mp4).decode()\n", + " video = open(fname,'rb').read() \n", + " data = \"data:video/mp4;base64,\" + b64encode(video).decode()\n", " \n", " html = \"\"\"\n", "
\n", " \n", "
\n", " \"\"\"\n", " \n", - " return display(HTML(data=html % data))\n", + " return display(HTML(data=html % (data, extension)))\n", "\n", " elif fname.endswith(\"html\"):\n", " \n", @@ -153,6 +156,13 @@ "## Matplotlib" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Please note that the example below are using the `vp80` codec to create a video which can be played in a browser and also this documentation. Nevertheless, without specifing the codec `mp4v` is used by default." + ] + }, { "cell_type": "markdown", "metadata": { @@ -166,7 +176,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 26, "metadata": { "collapsed": false, "jupyter": { @@ -186,7 +196,7 @@ "from pyrecorder.converters.matplotlib import Matplotlib\n", "\n", "# create a writer that takes the \n", - "writer = Video(\"example.mp4\")\n", + "writer = Video(\"example.webm\", codec='vp80')\n", "\n", "# use the with statement to close the recorder when done\n", "with Recorder(writer) as rec:\n", @@ -219,7 +229,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 27, "metadata": { "collapsed": false, "jupyter": { @@ -236,7 +246,7 @@ "\n", "
\n", " \n", "
\n", " " @@ -250,7 +260,7 @@ } ], "source": [ - "display(\"example.mp4\")" + "display(\"example.webm\")" ] }, { @@ -262,7 +272,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -276,7 +286,7 @@ "# initialize the converter which is creates an image when `record()` is called\n", "converter = Matplotlib(dpi=120)\n", "\n", - "writer = Video(\"example2.mp4\")\n", + "writer = Video(\"example2.webm\", codec='vp80')\n", "\n", "rec = Recorder(writer, converter=converter)\n", "\n", @@ -303,7 +313,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -312,7 +322,7 @@ "\n", "
\n", " \n", "
\n", " " @@ -326,7 +336,7 @@ } ], "source": [ - "display(\"example2.mp4\")" + "display(\"example2.webm\")" ] }, { @@ -338,7 +348,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 30, "metadata": { "collapsed": false, "jupyter": { @@ -397,9 +407,7 @@ "| `Julian Blank `_ (blankjul [at] egr.msu.edu)\n", "| Michigan State University\n", "| Computational Optimization and Innovation Laboratory (COIN)\n", - "| East Lansing, MI 48824, USA\n", - "\n", - "\n" + "| East Lansing, MI 48824, USA\n" ] } ], @@ -424,4 +432,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} diff --git a/pyrecorder/scratch.py b/pyrecorder/scratch.py index 21ee813..76c9be2 100644 --- a/pyrecorder/scratch.py +++ b/pyrecorder/scratch.py @@ -1,24 +1,34 @@ import matplotlib.pyplot as plt import numpy as np +from pyrecorder.converters.matplotlib import Matplotlib from pyrecorder.recorder import Recorder from pyrecorder.writers.gif import GIF -from pyrecorder.writers.video import Video -# create a writer object (here, mp4) -writer = Video("video.mp4") +# initialize the converter which is creates an image when `record()` is called +converter = Matplotlib() -writer = GIF("github.gif") +writer = GIF("medium2.gif", duration=0.5) -# use the with statement to close the recorder when done -with Recorder(writer) as rec: +rec = Recorder(writer, converter=converter) - # record 10 different snapshots - for t in range(10): +for t in range(50): - # create the plot (here, using matplotlib) - X = np.random.random((50, 2)) - plt.scatter(X[:, 0], X[:, 1], facecolor="none", edgecolor="red") + # let us create a local figure object with two sub figures + fig, (ax1, ax2) = plt.subplots(2, figsize=(3, 4)) - # use the record to store the current plot - rec.record() + X = np.random.random((100, 2)) + ax1.scatter(X[:, 0], X[:, 1], color="green") + + X = np.random.random(5) + ax2.pie(X) + # ax2.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle. + + # fix the size of figure and legends + fig.tight_layout() + + # take a snapshot the specific figure object with the recorder + rec.record(fig=fig) + + +rec.close() \ No newline at end of file diff --git a/pyrecorder/writers/video.py b/pyrecorder/writers/video.py index e17046e..c9ad1c8 100644 --- a/pyrecorder/writers/video.py +++ b/pyrecorder/writers/video.py @@ -7,7 +7,7 @@ class Video(Writer): def __init__(self, fname, - codec=cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), + codec='mp4v', fps=1, ) -> None: super().__init__() @@ -18,10 +18,17 @@ def __init__(self, self.file = None def write(self, frame, n_frames=1): - if self.file is None: height, width, layers = frame.shape - self.file = cv2.VideoWriter(self.fname, self.codec, self.fps, frameSize=(width, height)) + + fourcc = self.codec + if isinstance(fourcc, str): + fourcc = cv2.VideoWriter_fourcc(*self.codec) + + self.file = cv2.VideoWriter(self.fname, + fourcc, + self.fps, + frameSize=(width, height)) for k in range(n_frames): self.file.write(frame) diff --git a/setup.py b/setup.py index 426967b..d7dbf95 100644 --- a/setup.py +++ b/setup.py @@ -35,6 +35,8 @@ 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', 'Topic :: Scientific/Engineering :: Visualization', 'Topic :: Multimedia :: Recorder' ]