<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <title>Blog entries tagged screencast :: mwop.net</title>
    <description>Blog entries tagged screencast :: mwop.net</description>
    <pubDate>Thu, 20 Sep 2012 17:30:00 -0500</pubDate>
    <generator>Laminas_Feed_Writer 2 (https://getlaminas.org)</generator>
    <link>https://mwop.net/blog/tag/screencast</link>
    <atom:link rel="self" type="application/rss+xml" href="https://mwop.net/blog/tag/screencast/rss.xml"/>
    <item>
      <title>Screencasting on Linux</title>
      <pubDate>Thu, 20 Sep 2012 17:30:00 -0500</pubDate>
      <link>https://mwop.net/blog/2012-09-20-screencasting-on-linux.html</link>
      <guid>https://mwop.net/blog/2012-09-20-screencasting-on-linux.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>I've been wanting to do screencasts on Linux for some time now, and my big
stumbling block has been determining what tools to use.</p>
<p>The <strong>tl;dr</strong>:</p>
<ul>
<li>Use <code>recordMyDesktop</code> to record video clips, but afterwards, re-encode them
to AVI (<a href="#script">see the script I used</a>)</li>
<li>Record audio to WAV, or convert compressed audio to WAV format afterwards.</li>
<li>Use OpenShot to stitch clips together and layer audio and video tracks.</li>
<li>Remember to reset the video length if you change the playback rate.</li>
<li>Export to a Web + Vimeo profile for best results.</li>
</ul>


<h2>Stumbling Blocks</h2>
<p><code>recordMyDesktop</code> is a fairly simple tool, and allows you to record actions
you're taking, and simultaneously capture audio. However, it creates an &quot;.ogv&quot;
(Ogg Vorbis video file) — which is basically useless for anybody not on Linux
or FreeBSD. Additionally, I often like to record in segments; this makes it
less likely that I'll make mistakes, and, if I do, I only need to record a
small segment again, not the entire thing. <code>recordMyDesktop</code> is only for
creating screencasts, not merging them.</p>
<p>So, <code>recordMyDesktop</code> went into my toolbox for the purpose of recording the
video portion of my screencasts.</p>
<p>Which brings me to the next point: I also prefer to record the audio separately
from the screencast portion itself; this way I don't get typing sounds in the
recording, and I'm less likely to lose my train of thought as I'm speaking. To
this end, I ended up using quite simply the &quot;Sound Recorder&quot; utility
(<code>gnome-sound-recorder</code>). It's not great, but with a reasonable microphone, it
gets the job done. I chose to record the audio as MP3 files.</p>
<p>However, this means that I now have video and audio tracks. So my toolbox
needed a utility for overlaying tracks and laying them out on a timeline
independently.</p>
<p>I looked at a few different free tools for Linux, including <code>Avidemux</code>,
<code>Cinelerra</code>, and <code>PiTiVi</code>. <code>Avidemux</code> was not featurful enough, <code>Cinelerra</code> was
too difficult to learn (it's more of an advanced user's tool), and <code>PiTiVi</code>
kept crashing on me. So, I used the lazyweb, and tweeted a question asking what
others were using — and the unanimous response was <code>OpenShot</code>
(<a href="http://www.openshotvideo.com/">http://www.openshotvideo.com/</a>).</p>
<p><code>OpenShot</code> hit the sweet spot for me -- it was easy to pick up, and didn't
crash. However, I discovered problems when I exported my project to a video
file. My video, regardless of whether or not I changed the playback rate,
always played at about 2X normal speed. The audio always truncated 1 to 2
seconds before completion.</p>
<p>In doing some research, I discovered:</p>
<ul>
<li>There are known issues with Ogg Vorbis video files. Evidently, the
compression creates issues when re-encoding the video to another format.</li>
<li>Similarly, compressed audio can lead to issues such as truncation.</li>
</ul>
<p>Since <code>recordMyDesktop</code> doesn't allow you to select an alternate video codec, I
had to use <code>mencoder</code> to transcode it to another format. I chose AVI (Audio
Video Interleave, a video container format developed by Microsoft), as I knew
it had widespread support, using an mpeg4 codec (also widely supported). I used
the following script, found at
<a href="http://askubuntu.com/questions/17309/video-converter-ogv-to-avi-or-another-more-common-format">http://askubuntu.com/questions/17309/video-converter-ogv-to-avi-or-another-more-common-format</a>,
in order to encode my files:</p>
<pre><code class="language-bash hljs bash" data-lang="bash"><span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> *.ogv;<span class="hljs-keyword">do</span>
    newFile=<span class="hljs-variable">${f%.*}</span>
    mencoder <span class="hljs-string">"<span class="hljs-variable">$f</span>"</span> -o <span class="hljs-string">"<span class="hljs-variable">$newFile</span>.avi"</span> -oac mp3lame -lameopts fast:preset=standard -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=4000
<span class="hljs-keyword">done</span>
</code></pre>
<p>That solved the video issue, but I still had to solve the audio issues. I
quickly re-recorded one audio segment in Sound Recorder, and told it to use the
&quot;Voice,Lossless (.wav type)&quot;. When I used this version of the audio, I had no
issues, other than the audio length being mis-reported within <code>OpenShot</code>.
Instead of re-recording all segments, I installed the &quot;Sound Converter&quot; utility
(<code>sudo aptitude install soundconverter</code>), and used that to convert all my MP3
files to WAV. Interestingly, <code>OpenShot</code> reported the audio lengths correctly
this time; go figure.</p>
<p>Once that was done, I was able to start stitching everything together. A few
notes, in the hopes others learn from my mistakes:</p>
<ul>
<li>Several times, I wanted my video to playback slower. This is very easy to do:
right click on the clip, select &quot;Properties&quot;, and select the &quot;Speed&quot; tab, and
adjust as necessary. However, that's not all you need to do; you need to also
re-adjust the <em>length</em> of the clip. Simply take the existing length, and
divide it by the rate of play. As an example, if the length is 44 seconds,
and you specify a 1/2 rate (0.5), you'd do 44 / 0.5 = 88, and set the length
of the clip to 88s.</li>
<li>If you find that <code>OpenShot</code> is reporting your audio clip lengths incorrectly,
use another tool to find the accurate length, and then set the length to
that. I typically rounded up to the next second, as most tools were giving
the floor value from rounding.</li>
<li>I chose to export using the Web + Vimeo HD profile. This worked perfectly for
me. It created an mpeg4 file that I could preview in a browser, and then
upload without issues. Your mileage may vary.</li>
</ul>
<p>Hopefully, this will serve as a reasonable guide for others foraying into screencasts on Linux!</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-09-20-screencasting-on-linux.html">Screencasting on Linux</a> was originally
    published <time class="dt-published" datetime="2012-09-20T17:30:00-05:00">20 September 2012</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>ZF2 Modules Quickstart (Screencast)</title>
      <pubDate>Wed, 19 Sep 2012 13:10:00 -0500</pubDate>
      <link>https://mwop.net/blog/2012-09-19-zf2-module-screencast.html</link>
      <guid>https://mwop.net/blog/2012-09-19-zf2-module-screencast.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>One of the exciting features of the newly released Zend Framework 2 is the new module system.</p>
<p>While ZF1 had modules, they were difficult to manage. All resources for all
modules were initialized on each request, and bootstrapping modules was an
onerous task. Due to the difficulties, modules were never truly
&quot;plug-and-play&quot;, and thus no ecosystem ever evolved for sharing modules.</p>
<p>In Zend Framework 2, we've architected the MVC from the ground up to make
modular applications as easy as possible. Within ZF2, the MVC simply cares
about events and services — and controllers are simply one kind of service. As
such, modules are primarily about telling the MVC about services and wiring
event listeners.</p>
<p>To give you an example, in this tutorial, I'll show you how to install the Zend
Framework 2 skeleton application, and we'll then install a module and see how
easy it is to add it to the application and then configure it.</p>


<p>To keep things simple, I'm using a unix-like environment. As such, if you are
on Windows, you may not have the same command-line tools available. If you are
in such a situation, perhaps try this inside a Linux virtual machine.</p>
<p><a href="https://vimeo.com/49775540">Zend Framework 2 Module Quickstart</a></p>
<p>Let's start by creating a new project. We'll execute a few commands to download
a skeleton application archive and extract it.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ mkdir newproject
$ <span class="hljs-built_in">cd</span> newproject
$ wget https://github.com/zendframework/ZendSkeletonApplication/tarball/master \
&gt; -O ZendSkeletonApplication.tgz
$ tar xzf ZendSkeletonApplication.tgz --strip-components=1
</code></pre>
<p>The Zend Framework skeleton application can be downloaded directly off of
<a href="https://github.com">GitHub</a>. I'm showing using the download from master, but
you can also download a tarball or zipball for individual tags as well. Because
the download URL does not include an extension, I use the <code>-O</code> switch to tell
<code>wget</code> what filename to save to.</p>
<p><code>tar</code> has a nice option, <code>--strip-components</code>, which allows you to tell it
to descend a certain number of levels deep into the archive when deflating.
Since I know the tarball has a top-level directory named after the repository
and a sha1, I'm simply telling <code>tar</code> to skip that and give me the contents of
its child directory.</p>
<p>At this point you have the skeleton application, but it has no dependencies —
not even Zend Framework itself! Let's rectify that situation. We'll use the
dependency management tool <a href="https://getcomposer.org/">Composer</a> to do this. We
include the Composer phar file within the skeleton application to make this
fairly easy. Simply execute the following:</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ php composer.phar install
</code></pre>
<p>You may get a notice indicating that the composer version is older, and to run
<code>self-update</code>; you can ignore that for now.</p>
<p>If all goes well, you should now have Zend Framework installed. Let's test it
out. I'm going to use the built-in web server in PHP 5.4 to demonstrate.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ <span class="hljs-built_in">cd</span> public
$ php -S localhost:8080
</code></pre>
<p>If I browse to <code>http://localhost:8080</code> I should now see the landing page for
the skeleton application.</p>
<p><img src="/images/screencasts/2012-09-19-zf2-module-screencast-01-zsa.png" alt="" /></p>
<p>Let's add a module to the application. Many sites require a contact form. I've
written one as a module some time ago, and called it
<a href="https://github.com/weierophinney/PhlyContact">PhlyContact</a>. To install it,
I'll edit my project's <code>composer.json</code> and tell it about that dependency:</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"require"</span>: {
        <span class="hljs-string">"php"</span>: <span class="hljs-string">"&gt;=5.3.3"</span>,
        <span class="hljs-string">"zendframework/zendframework"</span>: <span class="hljs-string">"dev-master"</span>,
        <span class="hljs-string">"phly/phly-contact"</span>: <span class="hljs-string">"dev-master"</span>
    }
}
</code></pre>
<p>I know the name of the component from <a href="http://packagist.org/">http://packagist.org/</a>,
and I'm telling Composer that I want to use whatever the latest version is on
its master branch on GitHub. I happen to also know that PhlyContact requires a
dev-master version of Zend Framework, so I'll alter that dependency for now.</p>
<p>Now, we need to tell composer to update our dependencies.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ php composer.phar update
</code></pre>
<p>After executing the command, we should now see that it has installed; this may
take a little while.</p>
<p>You need to inform the application about the module. This is so that we don't
have to perform expensive file-system scanning operations, but also to make it
explicit in your code what modules you're actually using. Enabling a module is
usually as easy as adding an entry to <code>config/application.config.php</code>:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-string">'modules'</span> =&gt; <span class="hljs-keyword">array</span>(
    <span class="hljs-string">'Application'</span>,
    <span class="hljs-string">'PhlyContact'</span>,
),
</code></pre>
<p>This particular module provides some reasonable defaults. In particular, it
uses a CAPTCHA adapter that doesn't require additional configuration, and
assumes that you will want to use the default <code>Sendmail</code> mail transport. As
such, we can simply browse to it now. I happen to know that the module defines
a <code>/contact</code> end point. Let's fire up our PHP web server again, and browse to
that URL.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ <span class="hljs-built_in">cd</span> public
$ php -S localhost:8080
</code></pre>
<p><img src="/images/screencasts/2012-09-19-zf2-module-screencast-02-contact.png" alt="" /></p>
<p>It just works!</p>
<p>One philosophy we have for distributable modules in Zend Framework 2 is that
you should not need to touch the code in modules you install in your
application. Instead, you should be able to configure and override behavior
within the application configuration or in your application's site-specific
modules. Let's alter the contact module to:</p>
<ul>
<li>first, change the URL it responds to, and</li>
<li>second, use the &quot;file&quot; mail transport.</li>
</ul>
<p>Let's look at the default configuration. I'll browse to
<code>vendor/phly/phly-contact/config/</code> and look at the <code>module.config.php</code> file.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">return</span> <span class="hljs-keyword">array</span>(
    <span class="hljs-string">'phly_contact'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'captcha'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'class'</span> =&gt; <span class="hljs-string">'dumb'</span>,
        ),
        <span class="hljs-string">'form'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'contact'</span>,
        ),
        <span class="hljs-string">'mail_transport'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'class'</span> =&gt; <span class="hljs-string">'Zend\Mail\Transport\Sendmail'</span>,
            <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
            )
        ),
        <span class="hljs-string">'message'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-comment">/*
            'to' =&gt; array(
                'EMAIL HERE' =&gt; 'NAME HERE',
            ),
            'sender' =&gt; array(
                'address' =&gt; 'EMAIL HERE',
                'name'    =&gt; 'NAME HERE',
            ),
            'from' =&gt; array(
                'EMAIL HERE' =&gt; 'NAME HERE',
            ),
             */</span>
        ),
    ),

    <span class="hljs-comment">/* ... */</span>

    <span class="hljs-string">'router'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'routes'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'contact'</span> =&gt; <span class="hljs-keyword">array</span>(
                <span class="hljs-string">'type'</span> =&gt; <span class="hljs-string">'Literal'</span>,
                <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                    <span class="hljs-string">'route'</span> =&gt; <span class="hljs-string">'/contact'</span>,
                    <span class="hljs-string">'defaults'</span> =&gt; <span class="hljs-keyword">array</span>(
                        <span class="hljs-string">'__NAMESPACE__'</span> =&gt; <span class="hljs-string">'PhlyContact\Controller'</span>,
                        <span class="hljs-string">'controller'</span>    =&gt; <span class="hljs-string">'Contact'</span>,
                        <span class="hljs-string">'action'</span>        =&gt; <span class="hljs-string">'index'</span>,
                    ),
                ),
                <span class="hljs-string">'may_terminate'</span> =&gt; <span class="hljs-keyword">true</span>,
                <span class="hljs-string">'child_routes'</span> =&gt; <span class="hljs-keyword">array</span>(
                    <span class="hljs-string">'process'</span> =&gt; <span class="hljs-keyword">array</span>(
                        <span class="hljs-string">'type'</span> =&gt; <span class="hljs-string">'Literal'</span>,
                        <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                            <span class="hljs-string">'route'</span> =&gt; <span class="hljs-string">'/process'</span>,
                            <span class="hljs-string">'defaults'</span> =&gt; <span class="hljs-keyword">array</span>(
                                <span class="hljs-string">'action'</span> =&gt; <span class="hljs-string">'process'</span>,
                            ),
                        ),
                    ),
                    <span class="hljs-string">'thank-you'</span> =&gt; <span class="hljs-keyword">array</span>(
                        <span class="hljs-string">'type'</span> =&gt; <span class="hljs-string">'Literal'</span>,
                        <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                            <span class="hljs-string">'route'</span> =&gt; <span class="hljs-string">'/thank-you'</span>,
                            <span class="hljs-string">'defaults'</span> =&gt; <span class="hljs-keyword">array</span>(
                                <span class="hljs-string">'action'</span> =&gt; <span class="hljs-string">'thank-you'</span>,
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),
    <span class="hljs-comment">/* ... */</span>
);
</code></pre>
<p>Okay, that's interesting. I can define the captcha and options to use, the name
of the contact form, the mail transport I want to use, and even who the email
is sent from and who it goes to. In addition, it defines some routes.</p>
<p>I'll create a new file, <code>config/autoload/phly-contact.local.php</code>. This is a
local configuration file that will not be checked into my version control
system. Now, let's add some configuration. First, I'll configure my mail
transport.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">return</span> <span class="hljs-keyword">array</span>(
    <span class="hljs-string">'phly_contact'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'mail_transport'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'class'</span>   =&gt; <span class="hljs-string">'Zend\Mail\Transport\File'</span>,
            <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                <span class="hljs-string">'path'</span> =&gt; <span class="hljs-string">'data/mail/'</span>,
            ),
        ),
    ),
);
</code></pre>
<p>I'm telling the module to use the <code>File</code> mail transport, and telling the
transport where I want messages written. By default, Zend Framework calls
<code>chdir()</code> to change directory to the project root, so I can reference a
directory relative to that. I'm simply going to write to a <code>data/mail/</code>
directory. Let's create that, and make it world-writable for now to ensure the
web server can write to it. (In production, you'd only want it writable by the
web server user.)</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ mkdir -p data/mail
$ chmod a+rwX data/mail
</code></pre>
<p>Now, let's change the base URL the contact form responds to; I want it to
respond to <code>/contact-us</code>. Another principle of re-usable modules in ZF2 is that
we recommend creating tree routes for each module, with the root of the tree
being a literal route. This makes it easy to alter the base for routing,
without needing to redefine all the routes in the module.</p>
<p>I'll add the following to my local configuration, then. I'll simply override
the parent route for my module, named &quot;contact&quot;, and point it at a different
URL.</p>
<pre><code class="language-php hljs php" data-lang="php">    <span class="hljs-string">'router'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'routes'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'contact'</span> =&gt; <span class="hljs-keyword">array</span>(
                <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                    <span class="hljs-string">'route'</span> =&gt; <span class="hljs-string">'/contact-us'</span>,
                ),
            ),
        ),
    ),
</code></pre>
<p>Let's see if all this worked! Once again, I'll fire up PHP's built-in web
server.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ <span class="hljs-built_in">cd</span> public
$ php -S localhost:8080
</code></pre>
<p>Now, let's browse to <code>http://localhost:8080/contact-us</code> — looks good! Just as
an experiment, let's try the previously configured URL,
<code>http://localhost:8080/contact</code>. We get a 404 now!</p>
<p><img src="/images/screencasts/2012-09-19-zf2-module-screencast-03-config.png" alt="" /> <img src="/images/screencasts/2012-09-19-zf2-module-screencast-04-404.png" alt="" /></p>
<p>Now, let's submit the form. I'll fill in some information; it's asking for my
email address, a subject line, and a message, as well as for me to solve a
simple CAPTCHA. Once I've done all that, I can send it.</p>
<p>If all is well, we should now have a mail file in our data directory. Let's check.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ ls -l data/mail/
</code></pre>
<p>And now let's look at it.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ cat data/mail/ZendMail_1347989389_1009740165.tmp
Date: Tue, 18 Sep 2012 12:29:49 -0500
From: me@mwop.net
Reply-To: me@mwop.net
Subject: [Contact Form] Suspense!

Suspenseful, isn<span class="hljs-string">'t it?
</span></code></pre>
<p>Looks good!</p>
<p>Zend Framework 2 provides a wonderful modular architecture that will enable an
ecosystem of 3rd party modules that should save you time and energy when
developing your applications. I've demonstrated a simple one, a contact form,
but many, many more already exist, and with a stable release now available, you
should see that number grow. This is truly a wonderful step forward for
developers, and I hope you find it as exciting as I do.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-09-19-zf2-module-screencast.html">ZF2 Modules Quickstart (Screencast)</a> was originally
    published <time class="dt-published" datetime="2012-09-19T13:10:00-05:00">19 September 2012</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
  </channel>
</rss>
