# Recording functions re-enabled. Mostly there but need some help

**URL:** <https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653>\
**Category:** Dev Talk\
**Created:** [January 7, 2024, 7:25am UTC](https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653 "2024-01-07T07:25:43Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![dmandan](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@dmandan](https://discourse.libretime.org/u/dmandan)\
**Post date:** [January 7, 2024, 7:25am UTC](https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653/1 "2024-01-07T07:25:43Z")

</div>

Being able to record (and rebroadcast) is something that we’ve been needing for a long time and has stopped us from switching from Airtime to Libretime. I know a lot of others are keen to see this functionality.

I had a go at re-implementing these functions in Libretime over the holidays and made some progress - a lot of the code is still intact and I was able to get the recording part working well using Liquidsoap to record from the main source (which is always there and no sound card is required). The recordings are placed in the /app/recordings folder with all the metadata intact.

However, I really suck at Python and am floundering on the next step which is to get the recordings imported automatically as tracks (and rescheduled if required). It should be straightforward for someone who knows what they are doing… Again I think a lot of the code is still there.

Is there any chance someone could have a look at this? @joola @paddatrapper? My branch here:

> **[GitHub - GroundTruthNZ/libretime at record-and-rebroadcast](https://github.com/GroundTruthNZ/libretime/tree/record-and-rebroadcast)**
>
> record-and-rebroadcast

I’d be more than happy to do testing and tidyups!

---

<div class="post-metadata">

**Author:** ![joola](https://avatars.discourse-cdn.com/v4/letter/j/cab0a1/32.png) [@joola](https://discourse.libretime.org/u/joola)\
**Post date:** [January 7, 2024, 12:07pm UTC](https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653/2 "2024-01-07T12:07:28Z")

</div>

Hi @dmandan

Great that you try to tackle this one.

If you are ok with it, I think opening a Pull Request against the main branch will help us to give you feedback about your changes.

I check the code and I think some things must be cleaned up, and some things must be fully tested before going forward (e.g. passing json formatted object to the liquidsoap interactive vars, might require some escaping, also maybe we want to use a differetn method).

But I have other suggestions, but I’d rather continue this on Github.

Cheers

Jo

---

<div class="post-metadata">

**Author:** ![dmandan](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@dmandan](https://discourse.libretime.org/u/dmandan)\
**Post date:** [January 7, 2024, 7:02pm UTC](https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653/3 "2024-01-07T19:02:57Z")

</div>

Hi @joola

Thanks for your feedback - I’ll tidy up what I have working and make a PR in as you suggest,

Regards  
Dan

---

<div class="post-metadata">

**Author:** ![dmandan](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@dmandan](https://discourse.libretime.org/u/dmandan)\
**Post date:** [March 21, 2024, 6:39am UTC](https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653/4 "2024-03-21T06:39:59Z")

</div>

@joola @paddatrapper ?  
I made a PR - @joola had some feedback which I think I addressed. But nothing has happened since. I’m not sure what to do now. The recording is working in the PR and I’m sure it will be of value to many as is. I’d like to continue on and get the rebroadcasting working but if the recording functions aren’t going to be merged then there isn’t much point.

I appreciate that this is a labour of love and if nobody has had time to have a look at it yet that’s fine I’ll wait. If it is something else (e.g. crappy code that you don’t want to go near), that’s OK too. I can handle it. Just need to know. Thx.

---

<div class="post-metadata">

**Author:** ![paddatrapper](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.libretime.org/paddatrapper/32/675_2.png) [@paddatrapper](https://discourse.libretime.org/u/paddatrapper)\
**Post date:** [March 21, 2024, 9:50pm UTC](https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653/5 "2024-03-21T21:50:51Z")

</div>

Hey, I’m sorry I haven’t had a chance to review the PR yet. It definitely isn’t anything on you, I just have had approximately 0 spare time the last couple months. I will try prioritising reviewing it! Thank you for your contribution - it is very appreciated

---

<div class="post-metadata">

**Author:** ![dmandan](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@dmandan](https://discourse.libretime.org/u/dmandan)\
**Post date:** [March 21, 2024, 11:21pm UTC](https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653/6 "2024-03-21T23:21:24Z")

</div>

That’s all good - appreciate the response and the huge amount of work you put into this! Happy to wait - I just wasn’t sure if there was something else I needed to do.

---

<div class="post-metadata">

**Author:** ![joola](https://avatars.discourse-cdn.com/v4/letter/j/cab0a1/32.png) [@joola](https://discourse.libretime.org/u/joola)\
**Post date:** [March 23, 2024, 10:15am UTC](https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653/7 "2024-03-23T10:15:21Z")

</div>

Hi,  
My main concern was the amount of legacy and untested code.

I don’t remember the implementation detail, but I had a few concerns there as well, where we might have better options on how we record things. Have a discussion on what our different options are would be really helpful.

That said, i’ll try to take a look when I have more time, no promises. And I might push some fixes myself to see if we can get it in a mergeable state.

Thanks for the work so far,  
Cheers

---

<div class="post-metadata">

**Author:** ![dmandan](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@dmandan](https://discourse.libretime.org/u/dmandan)\
**Post date:** [June 27, 2026, 9:16am UTC](https://discourse.libretime.org/t/recording-functions-re-enabled-mostly-there-but-need-some-help/1653/8 "2026-06-27T09:16:24Z")

</div>

Got this working for us now - so put a PR through FWIW:  
[https://github.com/libretime/libretime/pull/3255](https://github.com/libretime/libretime/pull/3255)

> <https://github.com/libretime/libretime/pull/3255>
>
> This (re) enables the record and (optional) rebroadcast function that was origin…ally available in Airtime, except that it records using the master source stream. No sound card is required. And no extra binaries (Airtime used to use ecasound to record, but this uses Liquidsoap).
> 
> \<img width="300" alt="image" src="https://github.com/user-attachments/assets/12518a83-ddcf-4aa9-974f-713b10f26ac0" /\>
> 
> I had it half finished for a long time, but needed a little help (AI to the rescue) to get the recordings attached to the future scheduled broadcasts. 
> 
> Works well for us. Hopefully of value to others!
> 
> \### Changes Made
> 
> The recorder.py script is the main addition. Other changes are relatively minor.  
> 
> 
> \* \*\*ShowInstance Filter Support\*\* (views/show.py): Enabled exact matching on \`record\_enabled\` alongside bounds comparison (\`gte\`/\`lte\`/\`gt\`/\`lt\`) on show start and end times.
> \* \*\*Show Title Serialization\*\* (serializers/show.py): Added a read-only \`show\_name\` CharField pointing directly to the show's name, eliminating secondary lookups for playout.
> 
> \* \*\*v1 Client\*\* (v1.py): Added support for the \`/api/upload-recorded\` endpoint via \`upload\_recorded\_file\` to associate uploaded files and schedule future rebroadcasts.
> \* \*\*v2 Client\*\* (v2.py): Exposed \`list\_shows\_to\_record\` query to \`/api/v2/show-instances\` endpoint.
> 
> \* \*\*Liquidsoap Recording\*\* (ls\_script.liq): Added the \`start\_recording\` Liquidsoap script function and registered it as a server command.
> \* \*\*Liquidsoap Client\*\* (\_client.py): Exposes \`start\_recording(self, args: dict)\` telnet writer.
> \* \*\*ShowRecorder & Recorder Threads\*\* (recorder.py):
> \* \`ShowRecorder\` triggers stream recording, writes the ID3 tags, POSTs the file to \`/rest/media\`, and hits the legacy link endpoint to register the file and schedule future rebroadcasts.
> \* \`Recorder\` manages schedule synchronisation, bootstrapping, and spawning recording threads.
> \* \*\*Service Hooks & Testing\*\* (main.py, message\_handler.py, and message\_handler\_test.py): Integrated the queue and handler routing for show recording update/cancellation events.
> 
> \* \*\*Media Controller\*\* (MediaController.php): Automatically links show recordings and schedules rebroadcasts when the Python analyzer finishes metadata extraction and calls the \`PUT\` endpoint (at which point the file is no longer hidden in the library database and can be successfully scheduled).
> \* \*\*RabbitMqPlugin\*\* (RabbitMqPlugin.php): Emits RabbitMQ schedule update messages to the show recorder on calendar modifications.
> \* \*\*Add Show Template\*\* (add-show-form.phtml): Renders the record & rebroadcast settings section in the scheduling form.
