Looping a prerecorded page

My safety committee has asked me if there was a way to setup a prerecoded message and send it as a page, looping through it for a certain amount of time. As in, we need to evacuate the building, a user would dial a feature code on a phone, and it would play the prerecorded message 10 times. Would be great if it could play, wait x time and play again, for y number of times. But if it can only do a continuous loop, I’m OK with padding the recording with silence.

Yes - it is super simple, but not something that comes straight out of the box. The “hard way” is to set up an announcement that has a following another announcement (with the same message) that goes to another announcement (with the same recording again) six more times.

Short of that, you could easily write a simple custom context that does basically the same thing in a loop. If you do the dial plan route, you can build in the pause between as well.

OK. But how to I trigger it from an endpoint and send it through the multicast paging?

This question worries me. This is straight out of the drag-and-drool interface. That fact that you don’t know these two pieces of information tell me you should hire someone to click the following three buttons.

Set up the Custom Context (using the Custom Context option).
Set up a Miscellaneous Destination (using the Miscellaneous Destination)
Set up your Multicast Paging device as an extension and call it with the above.

Condescending much? It may come as a shock to a god like you, but some of us don’t play around with our PBX all day. That’s what I thought this community was supposed to be about. To learn how to use features that are off the beaten path.

1 Like

In case you don’t want to code it, Paging Pro has this as a native feature:

I recognize that it is in bad taste to reply to an old abandoned post, but this thread fits what I was looking for exactly.

I was not able to find adequate explanation in the manuals to help me figure out how to accomplish this using @cynjut’s recommendation (Custom Context + Miscellaneous Destination + Multicast Paging device extension). If someone wants to provide additional pointers to documentation for looping a prerecorded audio file in that manner, I would be very appreciative.

So instead this turned into my first FreePBX programming project. I’m posting the result here 1) in case it can help someone else 2) so that someone can tell me that there is a better way.

I set up a custom extension that:

  1. originates a call between a multicast device and an extension that quietly joins a conference bridge
  2. originates a call between an extension that loops the desired audio file and an extension that joins the same conference bridge
  3. connects the caller to the conference bridge muted to prevent feedback and as admin so that the paging stops when the caller disconnects

And it worked.

;;;
;;; Contents of extensions_custom.conf (abbreviated)
;;;

[from-internal-custom]
...
; include the context containing the emergency
; paging extensions
include => custom-emergency

[custom-emergency]
exten => *9001,1,Wait(1)
    same => n,Set(PAGE_LOOP_FILE_ID="all_clear")
    same => n,Goto(custom-page-loop,page_loop,1)

exten => **9002,1,Wait(1)
    same => n,Set(PAGE_LOOP_FILE_ID="severe_weather_drill")
    same => n,Goto(custom-page-loop,page_loop,1)

exten => *9002,1,Wait(1)
    same => n,Set(PAGE_LOOP_FILE_ID="severe_weather")
    same => n,Goto(custom-page-loop,page_loop,1)

[custom-page-loop]
exten => page_loop,1,NoOp()
    same => n,Answer()
    ; connect multicast devices to conference bridge
    same => n,Originate(MulticastRTP/basic/X.X.X.X:XXXXX//c(ulaw),exten,custom-page-loop,page_loop_enter,1)
    ; connect looping audio to conference bridge
    same => n,Originate(Local/page_loop_play_${PAGE_LOOP_FILE_ID}@custom-page-loop,exten,custom-page-loop,page_loop_enter_play,1)
    ; connect caller to conference bridge
    same => n,Set(CONFBRIDGE(user,template)=page_loop_admin)
    same => n,Set(CONFBRIDGE(bridge,template)=page_loop_bridge)
    same => n,Set(CONFBRIDGE(menu,template)=page_loop_admin_menu)
    same => n,ConfBridge(page_loop_1)
    same => n,Hangup()

; output to multicast devices
exten => page_loop_enter,1,NoOp()
    same => n,Answer()
    same => n,Set(CONFBRIDGE(user,template)=page_loop_user)
    same => n,Set(CONFBRIDGE(bridge,template)=page_loop_bridge)
    same => n,Set(CONFBRIDGE(menu,template)=page_loop_user_menu)
    same => n,ConfBridge(page_loop_1)
    same => n,Hangup()

; input from looping audio
exten => page_loop_enter_play,1,NoOp()
    same => n,Answer()
    same => n,Set(CONFBRIDGE(user,template)=page_loop_play)
    same => n,Set(CONFBRIDGE(bridge,template)=page_loop_bridge)
    same => n,Set(CONFBRIDGE(menu,template)=page_loop_user_menu)
    same => n,ConfBridge(page_loop_1)
    same => n,Hangup()

; looping audio with alert tones
exten => _page_loop_play_.,1,NoOp()
    same => n,Answer()
    same => n,Set(PAGE_LOOP_FILE_ID=${EXTEN:15})
    same => n(loop),Wait(1)
    same => n,Playback(/var/lib/asterisk/sounds/en/custom/3tones)
    same => n,Wait(1)
    same => n,Playback(/var/lib/asterisk/sounds/en/custom/${PAGE_LOOP_FILE_ID})
    same => n,Goto(loop)
    same => n,Hangup()


;;;
;;; Contents of confbridge_custom.conf
;;;

[page_loop_user]
type = user
quiet = yes
announce_user_count = no
wait_marked = no
end_marked = yes
dsp_drop_silence = yes
announce_join_leave = no
admin = no
marked = no
startmuted = yes

[page_loop_play]
type = user
quiet = yes
announce_user_count = no
wait_marked = no
end_marked = yes
dsp_drop_silence = yes
announce_join_leave = no
admin = no
marked = no
startmuted = no

[page_loop_admin]
type = user
quiet = yes
announce_user_count = no
wait_marked = no
end_marked = yes
dsp_drop_silence = yes
announce_join_leave = no
admin = yes
marked = yes
startmuted = yes

[page_loop_bridge]
type = bridge

[page_loop_user_menu]
type = menu
* = no_op

[page_loop_admin_menu]
type = menu
* = no_op

Thanks for opening this back up.
I’ve been looking for this solution myself. I’ll be giving it a try. I’ll let you know how it goes.