Home town news from Nevada City

November 24, 2007

I live in Nevada City, a small town in the foothills of the Sierra Nevada mountains, about 60 miles north-east of Sacramento. We have two (count ’em) Facebook groups, but not a lot of people.

The town itself only has about 3000 residents, though there’s probably 40,000 people within a 10 mile radius. So it’s not Moosejaw, Wyoming but it’s small enough that you don’t expect to bump into people who actually know of it, or live there.

But back in 2006, when we were launching Krugle at eTech in San Diego, up walks a guy from IBM with “Nevada City, CA” on his conference badge. David Fallside not only lives in town, he also manages one of IBM’s key open source groups. And now I run into him regularly at South Pine, our favorite breakfast place.

Next was a call from Mike Cassidy, one of the angel investors in Krugle. At the time he was still running Xfire, and he wanted to get in touch with Phil Wiser, the CTO of Sony America at that time. Mike had found out that Phil also lives in Nevada City – and eventually when I met Phil for breakfast, I realized he and his family were living in a house that I rode by several times a week.

Then I eating lunch during ApacheCon 2007 in George, chatting with two people who work for EMC. The guy mentions that he’s from California, I tell him I live in Nevada City, and he says “Oh yeah, one of the main people I work with lives there too.” It’s Gary Frankel, a regular member of the Tech Lunch group. We haven’t been doing well with our weekly gatherings, but for a while there we’d meet every Thursday for lunch at someplace like Tortilla Grill.

Finally, my brother-in-law pointed out an article in the most recent (November 2007) Smithsonian. It was “Beading the Way“, in the Around the Mall section. Joyce Growing Thunder Fogarty is one of the best American Indian beadworkers, and a dress she made is a highlight of the “Identity by Design” exhibition at the National Museum. This dress took 10 months of daily work, and the article talks about how she was helped by her daughter and graddaughter, who live in North San Juan. This is an even smaller town located about 10 minutes north of Nevada City, close to where my brother-in-law lives.

It’s hard to understand why the above stories have a special feeling, unless you’re one of the lucky few who live in a small town. But it helps me now understand the pleasure my parents took in finding obscure connections with strangers we’d meet during our annual cross-country Volkswagen car trips. Usually these involved Lutheran ministers and Wisconsin…

Video Editing Round 3 – InterWise Strikes Back

November 19, 2007

I just finished testing my CodeRage II presentation – or testing it as best I could, since InterWise doesn’t work with a Mac.

But somebody else on the training chat (Bob Swart, aka “Dr. Bob“) helpfully took a screenshot so I could see what he meant by “funny colors” in the video:

Mangled Video from InterWise

Nice, huh? Best I can tell is that InterWise is down-sampling the video from 1000s of colors (16 bit) to 256 colors (8-bit indexed), and that conversion isn’t working as well as it ought to. Bummer. But at least it’s still legible, and the audio seems fine. So no ugly editing required.

ApacheCon 2007 Atlanta

November 19, 2007

I’m back from my second ApacheCon, and frantically trying to triage my email in-box. As I unpacked, I came across the speaker gift – a 1GB USB flash drive, in a tasteful leather case with “ApacheCon US ’07 Speaker” tooling.

ApacheCon speaker gift

Sorry about the fuzzy photo, I don’t have a good macro lens.

Nothing earth-shattering, but I thought it was kind of funny to see the old-timey leather case on the flash drive.

The $800 Resistor Pack

November 19, 2007

Back in 1999 I had a house built. That wound up being an extremely stressful time in my life, as we’d also just moved to the Nevada City area, and my wife was pregnant. Word on the job site was that several sub-contractors bet the under for our marriage surviving, but that which does not kill us makes us stronger.

Once the house was actually done, life became much better. And we’ve been very, very happy with our house. Other than one thing. As that famous bard once wrote, “The first thing we do, let’s kill all the HVAC companies”.

I’ve got a panel house, built from SIPs – structural insulated panels. Very efficient, and very air-tight. The two kind of go hand-in-hand. Which means we need make-up air, a steady stream of fresh goodness from the outside so our dog’s fart doesn’t stink up the place for two weeks. Plus you can get sick house disease, where carpet chemicals, mold, and diapers can make you physically ill if you don’t get enough fresh air on a regular basis.

But when you bring fresh air in, old air has to go out. And this old air is air that we’ve carefully, painfully heated (or cooled) using natural gas or electricity. So venting air is essentially throwing good money and precious energy out the window – kind of like running the A/C with the front door open.

Enter something call an air-to-air heat exchanger, or heat recovery ventilator (HRV). This forces the air we’re venting to flow next to the air we’re pulling in, so that some of the energy we’ve expended to heat or cool the air inside the house gets transfered to the fresh air being pulled in from the outside.

So far, all good. Sounds like a great idea. And in theory it is. But then there’s reality:

  1. We wanted a 220 CFM (cubit feet/minute) HRV unit with 74% efficiency and a 320 watt power draw. The efficiency tells you how much of the potential energy is extracted from the inside air on its way out. The watts tell you how much power is needed to run the fans that pull and push the air through the system.
  2. What we got was a Carrier HRV model VC5BAB027000. This is a 200 CFM HRV unit with 68% efficiency that draws 500 watts. Unfortunately the general contractor signed off on this change, without talking to me or the engineer who did the energy calcs and drafted the original recommendation.
  3. After calculating the electrical cost of running the unit during the fall/winter, when compared to the cost of using gas to heat the air, we’re breaking even for half the year. And that doesn’t include the cost of the unit. If we were just basing it on energy cost, then you’d still have to factor in the energy required to build the unit, which is huge when it involves metal fabrication.
  4. Oh, and this unit had been discontinued two years before we had it installed. So the spare part situation was already heading downhill (see below) by the time we first switched it on.
  5. When I was trying to do the calculations for energy savings (above), I contacted Carrier to get the full specifications. Nope, can’t do that. I’m not a certified Carrier dealer. Now that just feels wrong. If I bought the unit, why is it OK for a company to refuse to send me information that I need to correctly operate it? This bugged me so much that I worked my way up through Carrier to the office of the president, but then the customer defense system proved too strong, and I was forced to admit defeat.
  6. Then the unit stopped working. About two years after the five year warranty expired. Nice. What failed were two relays on the circuit board. I’ve included the photo below, so you can understand why it makes sense for Carrier to charge $812 for a replacement. I mean, the relays alone are almost $3.

Carrier HRV Board

Now I’m not an electrical engineer, so perhaps my reasoning is off, but it looks to me like this board has got about 12 resistors, 13 diodes, 10 capacitors, three relays, two ICs, and a transformer. Total cost would be in the range of $5 – $10. Heck, I even looked up the price for the relays – $1.29 full retail per.

What’s interesting (as in the Chinese curse of “may you live in interesting times”) is that for parts distributors that have this in stock, it was $280, then $350, but now if you want it from Carrier it’s $812. Seems pretty clear that they’ve got a limited supply of these boards left, and the price heads up as boards get sold. Which, from a pure economic model makes sense, but from a customer loyalty perspective is dead wrong.

I’m in the midst of a startup (krugle.com) so my free time is virtually non-existent, but I’m still tempted to buy the two relays and try to replace them myself. There’s no way in hell I’m going to pay $812 for that board, so the other option is to throw away this $2400 unit and replace it with something new. The only bright spot is that I can get a more efficient model, with the air flow that I want, for about $1100 plus installation.

Anyway, a friend said that the fundamental problem is that HVAC companies are in the business of selling sheet metal, but they don’t want anybody to figure that out. So they create a closed network of dealers, restrict the flow of information, and pray each night that they don’t get hit with a consumer rights class action lawsuit.

Empowering reputable professionals

November 13, 2007

Recently I was trying to find out information about Mindaugus “Min” Idzelis, who wrote the Lucene-based search code for the Roller project. I was blogging about using search to solve impact analysis problems, and wanted to include a reference to him.

Hit #3 in a Google search on his name was from a site called naymez, with the tagline “empowering reputable professionals”. Unfortunately when I visited the web site and then clicked on his name to what what they had to say about Min, this is what I got:

Reputable Yahoo Ads

Now while I’m sure Min is a reputable professional, I was a bit distracted by the ads for sexy black singles and big beautiful women. These were auto-generated by Yahoo for the page, so the next time I visited I got boring (and more appropriate) ads for services in the Raleigh-Durham area.

Maybe it was just a glitch in the Yahoo ad system, but it made me very hesitant to include any kind of auto-ads on my pages…given some of the obscure things that I blog about, the odds of my getting a random and completely inappropriate ad seems pretty high.

Hand-to-hand combat with Mac videos

November 10, 2007

I just survived several days of intense fighting with my Mac, and thought I’d share my tale of woe.

The basic problem is that there seems to be a big product gap between the two uses cases of “I’ve got a 30 second home video I want to put on a DVD”, and “I’m a professional video editor”.

For example, I needed to create a 45 minute Flash video for the CodeRage II virtual developer conference that CodeGear (Borland) puts on every year. I’m giving a talk on “Impact Analysis for the Rest of Us”.

I used SnapzPro X to record the video on my G4 PowerBook, and ran into the following problems:

  • I couldn’t use H.263/H.264 to record, as otherwise the video would be blank. I wound up using Apple’s “Animation” codec, which didn’t compress it very well, but was reliable.
  • I couldn’t use audio compression, as otherwise it would be scratchy. So I went for mono/8-bit/22.050 KHz, to keep it reasonably small.
  • Sometimes the recording would be really scratchy. Once this was due to my mic (I’m using a Sennheiser headset), but the other two times it was SnapzPro…I could record with no problems using Quicktime. Restarting my Mac solved the problem both times. I hate restarting my Mac to “fix” a problem – it feels like a cop-out.
  • I was getting white flashes at the end of the video segments. Changing the key frame rate to every 3 frames seemed to solve that problem. Before that it was on “automatic”, so maybe that doesn’t work at low frame rates – I was only recording at 3 frames per second.

But now I had a number of video segments (30 seconds to 5 minutes in length) that I needed to clean up, then merge, and I had to be able to generate a Flash .flv file as the final product.

The upgrade to Quicktime Pro gave me the basic editing I needed, though the controls at the bottom of the movie for specifying segments should be improved. If you want to get rid of a 2 second snippet in a 400 second record, it’s a real PITA.

But when I tried pasting segments into one master QT movie, and then saving the result, I’d always get a “movie contains invalid data” error.

So then I purchased VisualHub, which can stitch together QT .mov files, and also save as Flash .flv. Unfortunately it can’t stitch Flash, so you have to first create a combo .mp4 file, and then convert that to Flash.

But the resulting Flash had a weird color shift, where everything was washed out. Working backwards, the problem happens during the conversion from .mov to .mp4. I found one post about this on the net, where the solution was to use the advanced VisualHub settings and force the conversion of .mov to .mp4 to use ffmeg (low level support) versus Quicktime. Huh? But it worked, which was great.

Oh, and setting the audio bitrate to 64 kbps in the Advanced settings helped remove most of the scratches and echos in the audio track.

Unfortunately using VisualHub to stitch files together caused another problem, where the audio/video tracks would get out of sync. The movie would wind up playing a few seconds faster than the audio – and since this was a tutorial, with lots of “so now I click on this thing” instructions, that wasn’t acceptable. Plus there were odd white flashes inserted between some of the movies.

Back to the drawing board. Turns out I can generate a combo movie and then export it from QTPro, even if I can’t save the results, and the exported move seems valid. So then I can just use VisualHub to convert that to Flash, and avoid any time skew.

But the conversion of 20 minutes of video suddenly took 80 minutes, which was much slower than before.

Ah, when exporting it I can save it using the same Sorenson 3 video codec as what Flash uses for its .flv format. And this then dropped the conversion time in VisualHub back down to a reasonable 13 minutes.

But I’m back to having color shift problems in the resulting move. Looks like the problem happens when converting from the color gamut used by the Animation codec to the color gamut used by the Sorenson 3 codec, at least when Quicktime is doing the conversion.

So my final solution was to export from Quicktime Pro using the same “Animation” codec, which generates huge files (400MB for my 40 minutes of video), but without any color shift. Then I take this combo file in VisualHub and convert it to Flash (.flv) with that funky “Force ffmpeg” advanced setting, and the end result is good. Plus there’s a bonus in that the conversion time is once again reasonable, about 15 minutes on my older, slower PowerBook.

Compared to the time required to outline, record, transcribe, edit, and re-record the presentation, the video editing time was probably an order of magnitude more.

And what’s really sad, if you use a Mac and believe that it really is “the digital hub” that Jobs talks about, is that the preferred solution for creating these types of presentations is to use Camtasia Studio, which is a Windows-only solution. But wait, there’s also Adobe’s Captivate – oh, but that’s also Windows only. I think Steve needs to stop by my office for a chat.

— Ken

Some additional notes from my experience –

  • I used setmy.browsersize.com to make my browser window exactly 1024×768.
  • I ran PowerPoint in it’s “fit to window” mode, and made it’s window match the browser window.
  • I used SnapzPro to record a fixed size (1024×768) movie at 3fps, then save as Apple Animation, 3fps, key frame ever three frames, thousands of colors, high quality. And the audio was no compression, 22.050 KHz, 8-bit, mono.
  • I’d open the resulting movie file with Quicktime Pro, then delete any gaps and mumbles, and save it to a new file.
  • When all the movie pieces were recorded, I copied the first piece, named it “Combo”, and then started inserting the other pieces one at a time. I’d open the next movie, select all, copy, close the movie, and then select “Add to movie” in the combo movie.
  • When I was done, I’d try to save the movie. Sometimes the worked, sometimes I’d get an error saying the movie contained invalid data. Using a lower value for the key frame rate seemed to reduce the odds of this happening.
  • Regardless, I’d then export it using the same video settings from SnapzPro, with a key frame every 3 frames.
  • Then I’d launch VisualHub and drag the exported combo movie into its window. I’d set the output format to be Flash, and check the “Raw .flv format” checkbox. In the advanced settings window, I’d check the “force: ffmpeg decoding setting”, set the framerate to 3, and set the audio bitrate to 64 (Kpbs), not 48 like the picture below.
  • Then I click the convert button and pray.

Some pictures of the process. First, the Quicktime export settings:


The VisualHub conversion window:


And the VisualHub advanced settings window:


WikiTrans round two

November 7, 2007

Back in January 2006, I wrote a blog post on the Krugle site titled WikiTrans – translation by the community.

Since then, I haven’t been able to spend any time even thinking about this topic, but two more recent sightings popped it back up in my mind.

First there was the October event at IMUG (International Mac Users Group), titled Collaborative Website Translation via the Worldwide Lexicon, by Brian McConnell. The short description is:

The Worldwide Lexicon Project is an open source, collaborative translation system for websites and publishers. The current version of WWL, available now for Word Press, Firefox and PHP based sites, enables a website’s readers, as well as volunteer or staff translators, to create, edit and share translations to and from almost any human language.

While this focuses on website translation, while I’m more interested in application translation, the goals are similar – how to create an open, collaborative system for translating (web sites, applications) from English into other languages.

And ideally doing it in a way where the results can automatically be used by the owner(s) of the original version to create/publish localized versions without much extra effort. As otherwise it just won’t happen.

Second, I noticed on the Chandler mailing list that there’s a big push for localization of the current version. And that, in turn, led to discussion about how to manage these translations. I wish I had the cycles to help out here, as it would be a fascinating project to create this type of system that could just plug into the Chandler development process.

The internet changed my name

November 7, 2007

Recently a guy we were interviewing here at Krugle pointed out that there were 176 hits (now 355) if you searched for “Ken Krugle” on Yahoo.

I can see why people might get it wrong, or maybe it’s just a typo – but even if I could change my surname to KrugleĀ® (hmm, wonder what the valid charset is for US names?), I think I’ll stick with “Krugler”.

But speaking of surnames, if anybody can point me to the definitive reference for valid characters, I’d like to add that to my list of obscure technical factoids.

What’s a techno tidbit?

November 6, 2007

A long time ago, I worked at the Apple Japan office while a small team of us where trying to kick KanjiTalk (Japanese OS for the Mac) out the door. There was a significant gap between most of the office, being focused on sales/marketing, and the development team. So I did a few talks on the technology behind KanjiTalk – Japanese text processing, input methods, fonts, etc.

I’m not sure how successful they were, but at least I can now recycle the name as the title for my blog.

A clearer error message?

November 6, 2007

We use Jive for the Krugle support bulletin board, and in general it works well. But recently we started getting errors while following links to posts, and contacted Jive support about the issue.

They responded with:

While I think that our system should fail more gracefully, and present you with a clearer error message, it appears that our software is operating normally.

I hope our support tries a bit harder than theirs, as the error message that could be a bit clearer is:

500 Servlet Exception

com.jivesoftware.forum.ForumThreadNotFoundException: Thread 378 could not
be loaded from the database.
at com.jivesoftware.forum.database.DbForumThread.loadFromDb(DbForumThread.java:1340)
at com.jivesoftware.forum.database.DbForumThread.<init>(DbForumThread.java:181)
at com.jivesoftware.forum.database.DatabaseCacheManager.getForumThread(DatabaseCacheManager.java:415)
at com.jivesoftware.forum.database.DbForumFactory.getForumThread(DbForumFactory.java:617)
at com.jivesoftware.forum.proxy.ForumFactoryProxy.getForumThread(ForumFactoryProxy.java:161)
at com.jivesoftware.forum.action.ForumThreadAction.loadObjects(ForumThreadAction.java:446)
at com.jivesoftware.base.action.interceptor.JiveObjectLoaderInterceptor.intercept(JiveObjectLoaderInterceptor.java:50)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.jivesoftware.forum.action.ForumsInterceptor.intercept(ForumsInterceptor.java:84)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.jivesoftware.base.action.interceptor.AuthInterceptor.intercept(AuthInterceptor.java:44)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.jivesoftware.forum.action.LocaleInterceptor.intercept(LocaleInterceptor.java:96)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:31)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:31)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.jivesoftware.base.action.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:41)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.jivesoftware.base.action.interceptor.JiveLoginInterceptor.intercept(JiveLoginInterceptor.java:41)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:31)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.opensymphony.xwork.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:151)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:31)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:189)
at com.opensymphony.xwork.DefaultActionProxy.execute(DefaultActionProxy.java:113)
at com.opensymphony.webwork.dispatcher.DispatcherUtils.serviceAction(DispatcherUtils.java:233)
at com.opensymphony.webwork.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:198)
at com.jivesoftware.base.action.util.JiveFilterDispatcher.doFilter(JiveFilterDispatcher.java:49)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.jivesoftware.util.SetResponseCharacterEncodingFilter.doFilter(SetResponseCharacterEncodingFilter.java:56)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118)
at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.opensymphony.webwork.dispatcher.ActionContextCleanUp.doFilter(ActionContextCleanUp.java:78)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.jivesoftware.base.stats.ReadStatsFilter.doFilter(ReadStatsFilter.java:80)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.jivesoftware.base.PresenceFilter.doFilter(PresenceFilter.java:105)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.jivesoftware.util.SetRequestCharacterEncodingFilter.doFilter(SetRequestCharacterEncodingFilter.java:72)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.jivesoftware.base.util.ApplicationInitializedFilter.doFilter(ApplicationInitializedFilter.java:59)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:163)
at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:208)
at com.caucho.server.hmux.HmuxRequest.handleRequest(HmuxRequest.java:396)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:363)
at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:490)
at com.caucho.util.ThreadPool.run(ThreadPool.java:423)
at java.lang.Thread.run(Thread.java:595)