Monday, January 19, 2015

QLab serial projector control with AppleScript

If you are using QLab for video cues, I suggest having it triggered by the light board as most projections need to be synchronized with lighting. That way projected scenery will fade in and out with area lighting during scene changes. It is fairly easy to connect a USB MIDI interface between the Mac and the "MIDI OUT" of your light board.

Most projectors have a RS-232 serial port which will allow you to do things like turn the projector on and off, switch video inputs, and close the shutter or "AV Mute" to save lamp life when there are no projections. The syntax of these serial commands is sometimes in the user manual, or available as a separate downloadable PDF from the manufacturer.

Tripp Lite makes an excellent VGA + Serial extender that works over CAT5 cable.

Power On - send this command when the light board operator runs the cue to warm up the lights - usually called a prewarm cue. You can auto-follow this into additional script cues to unmute and switch inputs to "reset" the projector for the top of the show and send a test image such as the classic indian head test pattern. Just make sure to put in a cue for preshow that fades out and stops this image and mutes the projector for the top of the show.

AV Mute - send this command after completing a fade to black that will stay up for a long time. This will preserve lamp life and prevent overheating.

AV Unmute - send this command to come out of AV Mute, wait 1 second then begin an image fade-in. Some projectors can come out of mute even faster.

Power Off - send this command at the end of the show - usually tied to the "house lights up" cue on the light board.

I use a StarTech USB Serial interface with OS X Mavericks. It makes both /dev/cu and /dev/tty "usbserial-FTXX7Z75" devices (A/B/C/D depending on how many ports your interface has) available to the operating system. The "cu" versions don't wait for flow control so you want to use these with the AppleScripts you put into QLab. To list the interfaces available on your Mac go to Terminal and type
ls /dev/cu*
There are two ways serial commands will be defined in your projector's user manual. They will either be ASCII or Hexadecimal. The ASCII commands are easier to script, but here are examples of both:

ASCII example:
-- Optoma W306ST Power On
set sCmd to "~0000 1" & (ASCII character 13)
do shell script "echo " & quoted form of sCmd & "> /dev/cu.usbserial-FTXX7Z75A"
Hexadecimal example:
-- Mitsubishi HC3 Power On
set sCmd to (ASCII character 92) & "x30"
set sCmd to sCmd & (ASCII character 92) & "x30"
set sCmd to sCmd & (ASCII character 92) & "x21"
set sCmd to sCmd & (ASCII character 13)
do shell script "echo -e " & quoted form of sCmd & "> /dev/cu.usbserial-FTXX7Z75A"
Notice in the Hexadecimal example above the echo command needs the -e switch so that it knows to parse \x30 as hexadecimal 30. Since AppleScript considers \ a special character, you need to build the sCmd string using (ASCII character 92) rather than just typing "\" into the character string.

A note on using VGA + Serial extenders: Some projectors' serial interfaces are finicky about the extender interfaces being turned off. I suggest putting these units on a separate power circuit from any power conditioner your QLab Mac is on. Keep them on all the time and the projector's serial port will always be responsive.

Friday, July 19, 2013

HTML5 Videos and FLVPlayer Integration

I've been working with HTML5 videos lately. There are several articles out there but nothing that specifically addresses how to fall back to Flash using FLVPlayer.

First thing you need to do is create three versions of your video: MP4, OGV and WEBM. Miro Video Converter is a free utility that can convert to all three formats. Even if you are starting with an MP4 video I suggest creating a new MP4 video from it in case it contains some metadata that is incompatible with all of the HTML5 video players out there. I've run into this on more than one occasion.

I'll use s3.company.com as a placeholder for the server that serves your videos and your FLVPlayer.

<html>
<head>
    <script type="text/javascript" src="http://s3.company.com/players/flvplayer155/swfobject/swfobject.js"></script>
    <script type="text/javascript">
        var flashvars = {
            flvpFolderLocation: "http://s3.company.com/players/flvplayer155/flvplayer/",
            flvpWidth: "720",
            flvpHeight: "480",
            flvpVideoSource: "http://s3.company.com/videos/video1.mp4",
            flvpInterfaceDisplay: "autohide",
            flvpInterfaceLayout: "overlay",
            flvpShowbCc: "false",
            flvpShowbMenu: "false",
            flvpShowbInfo: "false",
            flvpShowbForward: "false",
            flvpShowbBack: "false",
            flvpAutoStartMovie: "false",
            flvpVideoBuffer: "3",
            flvpVidConstraints: "fit to width",
            flvpTurnOnCorners: "false"
        };

        var params = {
            menu: "true",
            allowfullscreen: "true"
        };
                              
    </script>
</head>
<body bgcolor="#888888">  
    <video controls width="720" height="480">
        <source src="http://s3.company.com/videos/video1.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
        <source src="http://s3.company.com/videos/video1.ogv" type='video/ogg; codecs="theora, vorbis"'>
        <source src="http://s3.company.com/videos/video1.webm" type='video/webm'>
        <div id="flashUpgrade">
            <a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a>
        </div>
    </video>
    <script type="text/javascript">
        swfobject.embedSWF("http://s3.company.com/players/flvplayer155/FLVplayer.swf", "flashUpgrade", "720", "480", "9.0.0", "http://s3.company.com/players/flvplayer155/swfobject/expressInstall.swf", flashvars, params);
    </script>
</body>
</html>
  1. Since FLVPlayer builds its embed object using javascript, move the declarations for flashvars and params to the SCRIPT section in HEAD.
  2. Android and some other HTML5 players do not like AUTOPLAY in the VIDEO tag. Leave that out.
  3. Make sure the MP4 video is first in the list of all three video file SOURCEs for HTML5.
  4. FLVPlayer overwrites the flashUpgrade DIV with its embed code, so put its swfobject.embedSWF call in a SCRIPT section after /VIDEO so browsers that don't understand HTML5 will still load the flash video player. Don't autostart FLVPlayer either (flvpAutoStartMovie: "false" in flashvars).
  5. Replace 720 and 480 in all three locations with the dimensions of your video if different.

Thursday, October 25, 2012

Wired remote volume control for ClearOne Gentner AP800 matrix mixer

How to use the Arduino microcontroller to remotely control this matrix mixer.



The Gentner AP800 has 12 balanced inputs and 12 balanced outputs. Each of the 12 inputs can be assigned to one or more of the 12 outputs. The level of each input and output can be adjusted from -20dB to 20dB. In addition each input can be muted. However, the level at which an input is sent to a particular output is not adjustable. An input's level will determine its volume across all of the output channels it is assigned to.

This unit will work fine for my particular application, Halloween sound effect playback. I am using this matrix mixer to control the relative levels of different kinds of wind and music played through two sets of stereo speakers.

But I need a way to fine-tune the relative levels of sound effects while listening to them, rather than going back and forth between the sound rack and the listening location. Additionally, since the sound effects are stereo, I want a single knob that adjusts both the left and right volume simultaneously.

After reading the manual for the AP800 I discovered it can be completely controlled through its serial port. I decided to build a wired remote control that would use an Arduino to send serial commands to the AP800 as I adjust various potentiometers.



View Schematic
 

View Arduino Code

The Arduino's TTL serial output needs to be converted to RS-232 serial (different voltage) before it can be interfaced to the AP800. I am using the NKC RS232 to TTL converter (DTE).

There are two components: A "base station" and a "remote" that are connected together over standard CAT5 ethernet cable. If a crossover cable is used accidentally, nothing will be damaged, but the remote will not work.

The remote has a dim red LED to indicate that it is connected to the base station and is receiving power. An "unlock" button, while pressed, initiates a process on the Arduino to read the potentiometers and send the correct serial commands to the AP800.

I made this mostly out of spare parts I had laying around the shop. If I had a bigger remote box I would have added a third potentiometer and moved the mode selector to the remote. However, keeping the mode selector at the base station allows me to leave the volume remote out in one of the listening areas where I want to easily adjust the levels for that area without accidentally adjusting those for a different area.

The Arduino program has four sets of variables - ModeX_InputYZ - one set for each of the four modes selected by the rotary switch. These determine which inputs are controlled by the two potentiometers for each mode select setting.


Sunday, October 14, 2012

Pneumatic Jack in the Box, Part 3

To support the mask I built a frame out of perforated metal tape. I basically fit each piece into the mask from the inside, then attached the pieces together with small nuts and bolts. The frame was then screwed into a stand made of three pieces of 1x2 wood left over from the torsion box coffin lid project.

An additional piece of metal tape serves as the "jaw" and tucks neatly into the chin of the mask. I also bent out part of the metal tape to tuck into the nose. There was no need to glue or otherwise attach the mask to the metal perforated tape; the nose and jaw hold quite well on their own.


I attempted to mount the servo to the wood using pieces of rubber to cut down on vibration, but I do not think it helped much. The servo I used, the Hi Tec HS-82MG, uses metal gears and apparently this makes the servo very noisy.

At some point I may try the HS-81 servo which has identical specs to the 82MG except for having nylon gears.

Important: Observe the motion of the servo as it is controlled by the Arduino before attaching the horn and control wire. Make sure you know what position the servo is in (mouth closed or mouth open) before fastening the horn onto the servo and connecting the control wire to the mouth.

The first video below shows the inside of the mask frame.

After attaching the wooden stand to the accordion's top platform, I ran two cables. One regular speaker cable and a separate, shielded servo control cable. The two cables are zip-tied together and run down to the electronics enclosure to connect to the ELK-120 and the Arduino.

The servo control cable is shielded to prevent the servo from responding to stray EMF or interference from the high-level speaker signal. The outer shield connects to the AC chassis ground at the electronics enclosure end of the cable only. Three wires inside the shield are for signal ground, +5VDC from the power supply, and the servo control line from the Arduino.

The final phase was to "dress" the clown so that it didn't just look like a head on a platform. I created a shoulder and neck form out of tape and attached it around the head stand. I then draped black felt and blue satin cloth over the shoulders and attached it at the front and back of the inside of the box.

Finally, the purple frilly lace ruffle for the neck. This conveniently hides any part of the frame or shoulder form from showing as well. This was a little difficult to find, until I realized I could use a child-size tutu. Looks fine.

Videos:
10/04/12: Clown head with mouth servo
10/13/12: Demonstration of completed Jack-in-the-box halloween prop (featured below)




Start from the beginning: Pneumatic Jack in the Box, Part 1