Welcome back to another episode of “Hey, I did something!” Check out my author page for the other somethings I’ve done.
Today we’ll talk briefly about that most riveting of topics: workflows and music on hold in Skype for Business Server! If you have an aversion to PowerShell, close your eyes, I’ll try to be gentle. Just be forewarned, this blog post is much more “Wall ‘O Text” than some of my past ones.
Workflows and Music on Hold in Skype for Business
Let’s start off with a quick clarification of exactly what the music on hold in a workflow in Skype for Business is.
A workflow in Skype for Business acts a bit like the gate to your phone system for people calling in. If you don’t have Exchange integration and the auto attendant goodness that comes with it, you can use a workflow as an auto attendant (interactive workflow for those playing the home game), complete with all the “Press 1 for this” and “Press 2 for that,” we have all come to know and love from a phone tree.
The other type of workflow you can have is a hunt group workflow. This hunt group workflow can play a welcome message (either prerecorded or text-to-speech if you like the robot voice) and it can differentiate actions based on configured business hours (for example, “if during business hours, send the call to this queue” or, “If during non-business hours, play this message and forward to this voicemail” or, “If it’s a holiday, play this message and forward to this other voicemail”), but at the core of it, there’s no button pushing — it’s just a mechanism for routing the call where you want it, when you want it.
At this point you’re probably asking yourself, “Self, if I use a workflow and have it transfer to someone, what will the caller hear while it’s ringing the user/queue/voicemail/auto attendant?” That is an excellent question, and the answer is in Music on Hold. By default, this is an audio file that’s baked into Skype for Business that sounds something like a bad ringer on a ’90s flip phone.
The Issue at Hand
I was recently working with a client who is migrating from a legacy PBX to Skype for Business Server. One of the features of their legacy PBX was the ability to shuffle the hold music, and as a result, the client had a folder full of music that they had recorded for this purpose. Unfortunately, there’s not a native ability within Skype for Business to shuffle through songs. All you get is this:
So we get the option of that default pseudo music that’s pre-canned in Skype for Business, or hey, we can upload a music file. The operative part of that is “a music file,”not multiples, and if you upload another one, it replaces the one that you had there before. Great. Oh, and there’s no point in mashing all your songs together into one long file, it’ll restart at the beginning every time it starts to play, so you’re essentially stuck with your callers listening to the same song every time they call.
To overcome this “feature,” it’s time to play with some PowerShell. If you dabble around in the Skype for Business Management Shell a bit, you’re sure to find Set-CsRgsWorkflow. This nifty cmdlet would appear to be along the lines of all the other cmdlets that start with “Set” complete with a full complement of syntax you can use to modify attributes of workflows. Unfortunately, it’s not that complete and actually behaves a bit differently than other “Set” cmdlets. In fact, check out this plethora of options!
That’s a bit disappointing. I was hoping I could just Set-CSRgsWorkflow -Instance <workflow> -CustomMusicOnHoldFile “myfilename.wav” and life would be good. Time to dig deeper. “Get-help set-csrgsworkflow -detailed” gives us the answer that we want, though, in its third example:
Alright, now we’re getting somewhere … so, with this syntax, I have to use Get-Content on the .wav file I want to use, pipe it to Import-CsRgsAudioFile and store it into a variable. From there, I use Get-CsRgsWorkflow to store the workflow in a variable, modify the attribute of that new variable to equal the variable for the audio file and THEN use Set-CsRgsWorkflow to make the change I want. Thank you, Microsoft, I’m not sure you could have made this much more complicated, and please don’t take this as an invitation to make it more complicated.
But at least with this, we now have something we can make into a bit of a script that we can use to change out the music on hold. The problem here being that if you want a different song, you have to edit the script every time you run it and ain’t nobody got time for that!
With a little help from our folder full of properly formatted music (PCM, 8khz/16bit/mono), and the Get-Random cmdlet, we can turn this sucker into a poor man’s jukebox. I’ll show you the modified PowerShell first, then I’ll explain what’s going on.
$MusicFile = Get-ChildItem “C:\MusicFolder” | Get-Random | Get-Content -ReadCount 0 -Encoding Byte | Import-CsRgsAudioFile -Identity Service:ApplicationServer:<SFBserver.fqdn.com> -FileName “WorkflowHoldMusic.wav”
So what changed? Really, just the first part. We added a Get-ChildItem to pull the contents of our music folder, pipe that into Get-Random to randomly choose a file, then piped that into the existing Get-Content > Import-CsRgsAudioFile pipeline that was already there. All this does is randomly chooses a music file to push through the pipe and you follow it with all the rest of example and you’ve got your random songs on hold.
The client I’m working with has multiple campuses that they use workflows for, and music on hold is a big consideration for them because during business hours, they never want an auto attendant to answer, so each workflow plays a message and then rings a queue for 45 seconds before replaying the message and then ringing the queue for another 45 seconds. This can add up to a bit of time on hold, and as the workflow restarts the music from the beginning every time that cycle repeats itself, it’s important to them that the music is changed out on a fairly regular basis. We unfortunately can’t make it play a different song every time the cycle restarts, but we can at least make sure that today’s music isn’t the same as tomorrow’s music, so here’s what I saved to a .ps1:
$MusicFile1 = Get-ChildItem “C:\Hold Music” | Get-Random | Get-Content -ReadCount 0 -Encoding Byte | Import-CsRgsAudioFile -Identity Service:ApplicationServer:<SFBFE.FQDN.com> -FileName “WorkFlow1HoldMusic.wav”
$WorkFlow1 = Get-CsRgsWorkflow -Name “WorkFlow Campus 1”
$WorkFlow1.CustomMusicOnHoldFile = $MusicFile1
Set-CsRgsWorkflow -Instance $Workflow1
$MusicFile2 = Get-ChildItem “C:\Hold Music” | Get-Random | Get-Content -ReadCount 0 -Encoding Byte | Import-CsRgsAudioFile -Identity Service:ApplicationServer:<SFBFE.FQDN.com> -FileName “WorkFlow2HoldMusic.wav”
$WorkFlow2 = Get-CsRgsWorkflow -Name “WorkFlow Campus 2”
$WorkFlow2.CustomMusicOnHoldFile = $MusicFile2
Set-CsRgsWorkflow -Instance $Workflow2
$MusicFile3 = Get-ChildItem “C:\Hold Music” | Get-Random | Get-Content -ReadCount 0 -Encoding Byte | Import-CsRgsAudioFile -Identity Service:ApplicationServer:<SFBFE.FQDN.com> -FileName “WorkFlow3HoldMusic.wav”
$WorkFlow3 = Get-CsRgsWorkflow -Name “WorkFlow Campus 3”
$WorkFlow3.CustomMusicOnHoldFile = $MusicFile3
Set-CsRgsWorkflow -Instance $Workflow3
Drop that into a .ps1 file, modify it according to your environment, and now you’ve got a handy dandy script you can run whenever you want to change out your music. I’ve taken this an extra step and set it up as a scheduled task to run every night at midnight on the front end so it’s changed each morning when they come in. Item of note: after changing the music on hold, there does seem to be a bit of a delay where the workflow won’t be available to call for about 30 seconds to a minute after changing it, which is another reason I want it to run at midnight.
This is how I did it, but if anyone out there has another, possibly more elegant way of making this happen, or even a solution to that Holy Grail of changing the music every time the workflow runs, please drop me a line!
If you have any other questions about Skype for Business or need help getting this workflow to run, you can send us an email or give us a call at 502-240-0404!