Some video sites, like YouTube, provide a way to change the playback speed of the video. This allows you to watch content faster or slower than the standard speed. It is an incredibly useful feature for many people and until earlier this year, I thought it was ubiquitous. I am so used to using it that when I wanted to watch a video and it was not available, I got quite frustrated1.
Thankfully, a colleague showed me that all is not lost and I want to share the magic with you.
Above is the video I wanted to watch (source). It is an interesting video packed with useful information about testing, but it is quite long. I really wanted to watch it, but I did not have a lot of time available, so decided to watch it at a faster speed. However, I could not find a way to adapt the playback speed within the site's user experience. What to do?
In swoops my colleague, via Slack, to remind me that I have browser developer tools at my finger tips, primed to let me make it happen anyway. You can make this happen on the Vimeo site, the TestDouble site, or even here, on my blog.
In the world of HTML5, videos are embedded in pages using the video element. The video element implements the HTMLMediaElement interface (as does the audio element) and if you can get a reference to the video element in JavaScript, you can use this interface to manipulate the video playback.
The first step is getting the element. I did this in Google Chrome, but you should be able to do this in other browsers too, though the commands may be different. I right-clicked on the video and selected Inspect.
This should open the developer tools, with a node highlighted.
As seen in the screenshot above, the highlighted node was not the video element. Initially, I looked at the sibling elements and expanded likely candidates until I found the video tag I wanted, but there is an easier way. Use the Find command within the Elements tab of the Chrome developer tools by pressing ⌘+F (probably Ctrl+F on Windows).
Within the find bar, you can type <video and it will find the first video element in the page and, if there are more, allow you to cycle through any others until you get to the one you want. You can even tell if it is the one you want or not as both the node and the corresponding video are highlighted as seen in the screenshot below.
With the video element found, we can right click the DOM node in the developer tools and select Store as global variable.
This creates a global variable that we can use to manipulate the element. The console section is opened to show us the created variable and the element to which it refers.
Now we can use the variable (temp1 in this case) to adjust the playback rate (or anything else we wanted to do). For example, if we want to run at double speed, just change playbackRate to 2 by entering temp1.playbackRate = 2.
And that's it. Hit play on that video and it will now be running at twice normal speed. Want it to run at half speed instead? Set playbackRate to 0.5 instead. Want it to run at normal speed again? Just set playbackRate to 1.
I hope y'all find this as helpful as I have and next time you stumble because a common feature appears to be lacking, don't be afraid to crack open those developer tools and see what magical hackery you can perform.
I struggle every day. I know you do too. We may have similar struggles, or different ones. We may notice each others struggles, or we may not. What you may struggle with, I may find easy or not even realise is a thing. The same is true in reverse. Sometimes, I am struggling so hard, I forget you are too. I am really sorry about that. I do not mean to disregard you or your struggles, or give the impression that these things do not matter. That is one of my struggles.
Sometimes, when my heart is heavy with the anxiety of a personal revelation, a growth opportunity, I find it hard to see beyond to a point where it will all make sense again. So, I write things like this. I am not seeking pity or likes or anything like that. I only want to share how I am feeling in case you struggle with this thing too. I know it helps me to know I am not alone and sharing helps that, because if we never share our pain, how can we appreciate each other's joy?
I struggle between putting out into the world that somedays I feel broken, and "manning up", dealing with it privately like "men" do. Some folks reading this will not be able to look past the ideals they have of what it is to be strong and will see this as weak; that's one of their struggles.
And so, to close. Whatever you struggle with, it is okay to not be okay. Take some time. Sit in the sun with a cup of tea, or pet a cat, or whatever it is that helps you escape the moment and find a little pocket of peace. Maybe even share a story about it and help someone else who is finding that same struggle. You are stronger than you think and we are all stronger together than apart. You are loved. You are you, and no one else can be a better version of that than you already are. <3
This is a short post and hopefully incredibly helpful to some. There is (almost) a standard around finding out basic information about keyboard shortcuts in your favourite apps, and it came to my attention this week that not everyone knows about it. What I am about to tell you may change the way you use some of your most cherished applications forever, or it may not.
Almost every web application supports a keyboard shortcut for seeing more keyboard shortcuts using either ⇧ + / or ⌘ + /1. Using these you can quickly get to a summary of keyboard shortcuts for your app of choice. Even some locally installable desktop apps have taken to this "standard" shortcut for showing shortcuts. Go now and try it in something.
For those who aren't into experimenting with shortcuts, here are a few apps and their shortcuts shortcut. Search the table for your app of choice. If you happen to know about any other apps that use this approach should be in this list, let me know in the comments.
You might have noticed I took a little break from my blog recently. It was not intentional; things just got away from me a bit the last few months as I found a new job and had a nice vacation to see family in England (as well as a side trip to Edinburgh and the famous Fringe festival). Perhaps I will post more on the vacation another time; right now, I want to share my job news.
After a fantastic four years with CareEvolution, Inc., I recently accepted a software engineering position with Khan Academy. I am only a few weeks into my new position and I am still incredibly excited to have this opportunity. Not only am I working with some incredible people, we have tasked ourselves with an outstanding mission.
Our mission is to provide a free, world‑class education for anyone, anywhere.1
Leaving CareEvolution, Inc. was a difficult decision. Not only did it mean leaving behind extraordinary colleagues, it also meant leaving behind PowerShell, C#, Angular, and .NET as a part of my day-to-day profession. Instead, I will be working with React, Redux, Apollo, and Python. There is much for me to learn and, I hope, for me to blog about as I learn it. That said, I still love .NET things and will continue to tinker with them in my personal time2.
Of course, like my passion for .NET, some things will remain the same. Most significantly for me, the position is still remote and as such, provides me with great opportunities for personal growth as an offsite colleague and employee. I openly3 struggled with that while at CareEvolution, Inc. I hope that at Khan Academy, I can learn which parts of that struggle were down to the need for personal growth, and which, if any, were organisational. If I can, I will coalesce lessons I learn into a meaningful collection of tips that others might use to adapt their personal and organisational culture around remote work and off-site workers.
Finally, this blog is still my blog, these are my personal musings; nothing I post here represents the views of my employer. Thank you for your readership and your patience during my blog hiatus. As they say at work, onward!
BrowserStack has been an incredibly useful resource for tracking down bugs and testing fixes when I am working on websites. This often requires accessing locally deployed sites or sites accessible over a VPN connection, and to do that, BrowserStack needs some local code running to be able to route the traffic accordingly.
Up until recently, my browser of choice has been Google Chrome, for which BrowserStack provides a handy extension to add support for local sites. However, since the Windows Creators Update, I have been giving Microsoft Edge a shot1 and no such extension exists. Instead, BrowserStack provides a download, BrowserStackLocal.exe , and a secret with which to run it. This works great, but there are a couple of annoyances.
I have to remember to run it.
It is a blocking process.
There are a variety of ways this problem can be solved. I decided to take the opportunity to expand my PowerShell fu and put together some cmdlets to run the BrowserStackLocal process in the background. Specifically, I wanted to compare PowerShell jobs with plain old processes for this specific purpose.
First: Jobs
Since the running the command is a blocking operation, I decided to try wrapping it in a PowerShell job so that it would sit in the background. This is useful since the job gets terminated when the PowerShell session ends, which makes it less likely for me to forget. The downside is that each PowerShell session could have its own job, but only the one that started BrowserStackLocal will actually end it, but I was certain I could work with that.
Getting started
The first cmdlet for starting BrowserStackLocal is cunningly named Start-BrowserStackLocal , shown here:
This has basic room for improvement, like having the secret and the path be parameters to the cmdlet, or environment variables; I happened to stop tinkering once it worked for me, so feel free to expand on it.
At the start, we check to see if we already have a job for BrowserStackLocal since we only need one. If we do not, then we get on with making sure BrowserStackLocal can be found where we expect it. If everything looks good, then the job gets started.
To tackle the chance that my script may fail due to the BrowserStackLocal command either getting an incorrect key or discovering it is already running, I added a Wait-Job call. The nice thing here is that since normally BrowserStackLocal blocks, we can assume that if the job did not reach a completion state, then the executable command is running. I take advantage of that fact, so if the Wait-Job returns, we can assume things went wrong and dump the details of the problem back to the console.
Stopping the job
Once the job is running, we need to be able to terminate it.
This is a much simpler cmdlet than the one to start the job. It has two main tasks:
See if the job is actually running
If it is, stop it
I added some helpful output so we could see it working and that was that.
Problems with jobs
This solution using jobs works great but it is not ideal. Each PowerShell session has its own jobs, so you have to know which session actually started BrowserStackLocal in order to stop it. Not only that, but if PowerShell did not start it at all, you cannot stop it from there with these commands at all. Jobs are great but they are not really the right tool for this…er…job.
Second: Processes
The wise man would have probably started here. I did not because I wanted to learn about jobs. Now that I have, I am wiser and so, I thought I would recreate my success but this time using the Xxx-Process cmdlets of PowerShell.
Getting started again
Using processes, the start cmdlet looks like this:
Since the BrowserStackLocal executable starts more than one process, I added some loops to output information about those processes. Now if we try to start the command and it is already running, we will get the same feedback, regardless of where the command was started.
Stopping the process
Switching to processes makes the stop code a little more complicated, but only because I wanted to provide some additional detail (we could have just called Stop-Process BrowserStackLocal and it would stop all matching processes).
function Stop-BrowserStackLocal()
{
$processes = Get-Process BrowserStackLocal -ErrorAction SilentlyContinue
if (-Not $processes) {
Write-Host "BrowserStackLocal is not running"
return
}
Write-Host "Stopping BrowserStackLocal..." -ForegroundColor Yellow
foreach ($process in $processes) {
Write-Host " $($process.ID): $($process.Name)" -ForegroundColor Cyan
Stop-Process $process
}
}
Helpful aliases
Finally, to make the task of starting and stopping a little less arduous, I added some aliases (inspired by the helpful sasv and spsv aliases of Start-Service and Stop-Service).
TL;DR: Use processes to start processes in the background3.
The rest
I am pretty pleased with how this little PowerShell project worked out. I get to keep using Microsoft Edge with minimal effort beyond what I had when using Google Chrome for my BrowserStack testing, enabling me to take advantage of the performance and battery-life improvements Edge has over Chrome. Not only that, but I got to learn some new things about PowerShell.
You don't get closures entirely for free in PowerShell. I suspected this, but I learned the hard way. However…
We can pass local variables into script blocks using the $using:<variable> syntax instead of passing an argument list and adding parameters to our script.
Debugging jobs can be a pain until you learn the value of Receive-Job for getting error information.
Use Wait-Job with a little time out to give your job chance to fail so that you can spit out some error information.
You have to stop a job before you can remove it.
Don't use jobs to control background processes; use processes instead
I have not gone so far yet as to start the BrowserStackLocal service automatically, but I can see value in doing so, especially if I did a lot of BrowserStack testing on local sites every day (of course, I'd probably want to redirect the output to $null in that scenario rather than see feedback on the running processes with every shell I opened).
What are your thoughts? Do you use PowerShell jobs? Do you use BrowserStack? Will you make use of these cmdlets? Fire off in the comments.
Yes, the battery life is noticeably better than when using Chrome; yes, I am frustrated that I cannot clear cookies for a specific site [↩]