User Tools

Site Tools



I run this code to link an Owncast chat to a Matrix room.

It's designed to be temporary (you just run it from the command line) but it would be easy to modify to run as a cronjob and always be searching for when a stream starts.

I've seperated out the Owncast-to-Matrix and Matrix-to-Owncast components so you can choose which one you want (or run both).

OwncastToMatrix uses my very simple Matrix PHP Class but MatrixToOwncast doesn't require it. It should work as is, but might best serve as inspiration in your own language of choice.

$token = "YOUR_TOKEN_HERE"; // you may have to manually escape hypens with a backslash
$tracker_file = "/tmp/owncast_to_matrix.json"; // tracks which messages have been sent to Matrix already
   $tracker = json_decode(file_get_contents($tracker_file), true);
$endpoint = "/api/chat";
while(true) {
   $data = json_decode(file_get_contents($url.$endpoint), true);
   $last_slice = array_slice($data, -20);
   foreach($last_slice as $line) {
      if($line['type'] == "CHAT") {
         if(!array_key_exists($line['id'], $tracker)) {
            $str = "<Owncast: ".$line['author']."> ".htmlspecialchars_decode(strip_tags($line['body']), ENT_QUOTES);
            $tracker[$line['id']] = strip_tags($line['body']);
            if(!empty($str)) {
               $mat = new matrix();
               $room = "#geek";
               $mat->post($str, $room);
   file_put_contents($tracker_file, json_encode($tracker));
function get_new_events($room) {
   $tracking_file = "/tmp/listen_matrix_owncast.json";
   $since = file_get_contents($tracking_file);
      $since = "s1022334_0_0_0_0_0_0_0_0";
   $homeserver = "";
   $access_token = "YOUR_MATRIX_ACCESS_TOKEN HERE";
   $url = "https://$homeserver/_matrix/client/r0/rooms/$room/messages?access_token=$access_token&from=$since";
   $data = json_decode(file_get_contents($url), true);
   $new_tracking_data = $data['end'];
   file_put_contents($tracking_file, $new_tracking_data);
   return $data;
$room_id = "!room_id:homeserver";
$sender_name = "@botname:homeserver"; // IMPORTANT: Set this to the name of the user associated with the access token, this stops it from getting stuck in a loop (and repeating what is said in both rooms forever).
while(true) {
$data = get_new_events($room_id);
if(is_array($data['chunk']) and sizeof($data['chunk'])>0) {
   foreach($data['chunk'] as $message) {
      if($message['sender'] != $sender_name) {
         if($message['content']['msgtype'] == "m.text") {
            if(!empty($message['content']['body'])) {
               $nick_parts = explode(":", $message['sender']);
               $relay = "[".substr($nick_parts[0],1)."] ".$message['content']['body'];
               echo $relay."\n";
function send_owncast_system_message($str) {
      return false;
   $url = "";
   $access_token = "YOUR_OWNCAST_ACCESS_TOKEN_HERE"; // you may have to escape hyphens with a backslash
   $endpoint = "/api/integrations/chat/system";
   $post = array("body" => $str);
   $auth = "Authorization: Bearer $access_token";
   $ch = curl_init($url.$endpoint);
   $headers = array("Content-Type: application/json",
   curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   curl_setopt($ch, CURLOPT_POSTFIELDS,json_encode($post));
   $result = curl_exec($ch);

Then just run them on the command line with something like:

php OwncastToMatrix.php &
php MatrixToOwncast.php
projects/matrix_owncast.txt · Last modified: 2021/04/07 21:18 by admin