Monday, June 19, 2023

Lloyd's Screencast Teleprompter App



 "Video is the new PowerPoint," or so the saying goes, even though I'm a Google slides guy myself. I make a lot of videos for my teaching and most consist of me providing narration for a collection of slides. I use the "shelf life time ratio" to determine how much planning should go into each. That is, I do very little planning for a video I intend a specific audience to watch just once. For these, I'm basically "shooting from the hip" and making things up as I go. In contrast, a video with an intended long shelf life - videos I plan on using semester after semester - requires a lot of planning up front. The ratio is simply the longer the shelf life, the more planning that is required.

For long shelf life videos, I long ago learned to write scripts, at least for the very beginning of the video and key sections. Viewers will get turned off quickly if the first 30 seconds of the video is of a bumbling and stammering professor who isn't sure what he wants to say. But where to display one's scripts or notes while making the video? Sometimes I taped the script to the computer screen. Yet, I've made too many videos where it is painfully obvious that I'm reading something. You can see my eyes moving back and forth and you can slowly see my gaze go from top to bottom. I've tried posting small script portions on a stand or box sitting just behind my computer as close to the camera as possible. These results are better, but I'm forced to have a bunch of cuts as I trade out each new portion. I'd much prefer to be known as "one take Rieber." I've been struggling with this issue for almost 20 years. So, it kind of shocks me that it took me this long to have the idea to build my own teleprompter for screencasts.

For the record, I have tried using third party teleprompters in the past for videos where I'm being filmed without a computer. I've never been too comfortable with them. It's hard to get the speed right and it's a challenge of where to put them in relation to the camera. (You must realize that I have no budget and I am my own "video crew," so I'm constantly jerry-rigging up the equipment.) But, at least 97% of the videos I make are screencasts - me narrating a set of slides or some other application, with me in a small video window off to the side. What I really need is a small, compact teleprompter that can be displayed on the screen near the computer's camera with plenty of screen space remaining for the window I wish to film. It seemed like a perfect LiveCode project.

My Third Design Works Like a Charm

I'm very happy with the design of the app, but I had two painful failures at the start. I'll get to those later, but allow me to show you the current design. I'm still working on the graphic design, but my field tests of the functionality have gone very well. Here is a short video demonstration:

Here are some of the main design principles of the app:

  • Controlling the speed of the teleprompter needs to be easy and unobtrusive, so that the user could change the speed while narrating with virtually all attention devoted to the meaning of the text.
  • The teleprompter needs to consume very little screen space.
  • The teleprompter needs to be able to be positioned as close to the computer camera as possible so that it appears that the user is looking at the viewer.
  • The text size needs to be under the user's control.
  • The size of the teleprompter window needs to be under the user's control.
  • The text can be pasted into the teleprompter and then edited during the rehearsal of the narration.

Of these, the first is the most important. I needed a way to let the user alter the speed of the teleprompter easily throughout the narration, stopping it when necessary and even backing up if the need arose. Controlling the teleprompter speed needed to be as easy as possible requiring very little cognitive demands. I found that the best way to do this was through the use of mouse hovering over the control buttons with the teleprompter speed increasing or decreasing as the mouse moved right or left. This means that no mouse clicking is needed, the sound of which would likely have been picked up by the microphone.

Code Examples

The most important code is in the two green buttons. Here is the code for the one on the right, the one that propels the text in the prompter forward:

1:  global varScrollPosition   
2:  on mousewithin  
3:    set the locktext of field "prompter" to true  
4:    if varScrollPosition > the scroll of field "prompter"+2 then exit mousewithin  
5:    put item 1 of the mouseloc into varMouse  
6:    put ((varMouse-700)/25)+5 into varScrollSpeed    
7:    add varScrollSpeed to varScrollPosition  
8:    set the vScroll of field "prompter" to varScrollPosition  
9:  end mousewithin  
10:  on mouseleave  
11:    set the locktext of field "prompter" to false  
12:  end mouseleave  

The variable "varScrollPosition" controls the scrolling of the field "prompter." The variable "varScrollSpeed" controls the speed of the scrolling. The only tricky part of this code is shown in line 6. If you watch the video, you'll notice that the scrolling rate increases as the hovering mouse moves toward the right of this button. I wanted the range of scrolling speed to be from 5 to 25 pixels where 5 is very slow and 25 is very fast. The left edge of this button is 700 pixels to the right of the app window. So, I had to subtract 700 before dividing the location of the mouse by 25. This created a nice sliding scale from 0 to 25. I then added 5 so that the 5 would be the minimum scrolling speed when hovering over this button.

varScrollPosition needs to be a global variable so that the position of the scroll bar is maintained throughout the session.

I locked the text during scrolling, but unlocked it when not scrolling. This allows the user to edit the script while rehearsing.

Line 4 determines if varScrollPosition goes beyond the bottom edge of the field.  I couldn't find a system variable to tell me the range of the scrollbar, but I found system variable "scroll" that returns the current scroll position. It tops out once the scroll bar hits the bottom. So, the variables varScrollPosition and scroll are virtually the same until the scrolling reaches the bottom of the scroll bar. So, I plugged in this little formula to stop increasing varScrollPosition once it is more than 2 pixels more than scroll. 

The other options were all very simple to code. As one example, here's the code for the button that increases the vertical height of the teleprompter field:

1:  on mouseup  
2:    put the height of field "prompter" into varHeight  
3:    put the top of field "prompter" into varTop  
4:    add 10 to varHeight  
5:    set the height of field "prompter" to varHeight  
6:    set the top of field "prompter" to varTop  
7:  end mouseup  

This adds 10 pixels to the height of the field. I keep the top of the field fixed, so as the height increases, the length is added to the bottom.

All of the other options were equally simple to code to manipulate the format of the teleprompter field.

My First Two Designs Were a Disaster

I really like the simplicity of the final design in the way that it controls the system variable "vScroll." It contrasts mightily with my first two attempts. I had either forgotten or didn't know about the system variable "vScroll." So, I had concocted some very heavy handed approaches to getting the scrolling to work. I'm not going to even try to give the details, but here is a brief explanation.

I began by breaking down the script into individual characters. Line breaks would be added anytime a period was detected. I also figured that the user would want to insert line breaks at various places, so I added a search for the forward slash "/". I figured only three lines of the script would need to be shown at one time, so I created three variables, varSentence1, varSentence2, and varSentence3 to contain each. The idea was to create a type of cascading approach where the fourth sentence would become sentence 3, which would become sentence 2, which would become sentence 1. This would continue until the end of the script. I actually got it to work, but it was very hard to read as the sentences jumped abruptly from line to line. 

I could go on as there was more ugliness in these first two designs. Now you might think I'm embarrassed by such poor initial designs, but no, far from it. I've learned that the best designs don't appear magically at the first go. They take time to reveal themselves. The only way to finally get them to show up is to start on the journey and then always be on the lookout when you finally stumble across them. Yes, good - even great designs - almost always start off with failure.