Thank you for (REALLY) useful script. I am real newbie in the pipe topic but i just found out it handles the streams better as there are some parameters that help to keep the stream. I had really big issues with keeping the stream, well, streaming. But i found small issue with your script - it picks up just first 50 entries. I have more than 400 channels in my network so i decided to change it a bit (i just changed the API call to specify the limit to very high number). It now picks up 9999 channels (i think very few people has more than that lol). Here it is:
#!/bin/bash
# Tvheadend credentials and URL
TVH_USER="admin"
TVH_PASS="password"
TVH_URL="http://localhost:9981"
# Network Name to target
NETWORK_NAME="MYIPTVNETWORKNAME" # Change this to match your target network
# Fetch all MUXes by requesting a large limit value
MUXES=$(curl -s --digest -u "$TVH_USER:$TVH_PASS" "$TVH_URL/api/mpegts/mux/grid?start=0&limit=9999")
if [[ -z "$MUXES" ]]; then
echo "Error: No MUXes found in Tvheadend."
exit 1
fi
# Process each MUX in the targeted network
echo "$MUXES" | jq -c --arg net_name "$NETWORK_NAME" '.entries[] | select(.network == $net_name)' | while read -r mux; do
# Extract MUX UUID, Name, and Current URL
MUX_UUID=$(echo "$mux" | jq -r '.uuid')
MUX_NAME=$(echo "$mux" | jq -r '.name')
CURRENT_URL=$(echo "$mux" | jq -r '.iptv_url')
# Skip if the URL is already using ffmpeg pipe
if [[ "$CURRENT_URL" == pipe* ]]; then
echo "Skipping MUX: $MUX_NAME - already using ffmpeg pipe"
continue
fi
# Construct the new URL with ffmpeg
NEW_URL="pipe:///usr/bin/ffmpeg -reconnect 1 -reconnect_at_eof 1 -reconnect_streamed 1 \
-reconnect_delay_max 2000 -probesize 1000k -analyzeduration 0 -fpsprobesize 0 -fflags -nobuffer \
-err_detect ignore_err -i $CURRENT_URL -codec copy -f mpegts -tune zerolatency pipe:1"
# Form-encode the payload
PAYLOAD="node={\"uuid\":\"$MUX_UUID\",\"iptv_url\":\"$NEW_URL\"}"
# Send the update request
RESPONSE=$(curl -s --digest -u "$TVH_USER:$TVH_PASS" -X POST "$TVH_URL/api/idnode/save" \
-H "Content-Type: application/x-www-form-urlencoded" --data-urlencode "$PAYLOAD")
# If the response is empty, warn instead of failing
if [[ "$RESPONSE" == "{}" ]]; then
echo " Warning: No confirmation from API for MUX: $MUX_NAME, re-checking..."
sleep 2 # Wait before re-checking
# Fetch updated MUX list with the same pagination parameters
UPDATED_MUXES=$(curl -s --digest -u "$TVH_USER:$TVH_PASS" "$TVH_URL/api/mpegts/mux/grid?start=0&limit=9999")
UPDATED_URL=$(echo "$UPDATED_MUXES" | jq -r --arg uuid "$MUX_UUID" '.entries[] | select(.uuid == $uuid) | .iptv_url')
# Verify if the update was actually applied
if [[ "$UPDATED_URL" == "$NEW_URL" ]]; then
echo " Update confirmed for MUX: $MUX_NAME."
else
echo " Failed to confirm update for MUX: $MUX_NAME."
fi
elif echo "$RESPONSE" | grep -q '"success":true'; then
echo " Updated MUX: $MUX_NAME successfully."
else
echo " Failed to update MUX: $MUX_NAME. Response: $RESPONSE"
fi
done