feat(peertube): Add yt-dlp video import to LuCI dashboard

- Install yt-dlp in PeerTube LXC container for video downloads
- Add RPCD methods: import_video, import_status
- Add UI section with URL input and download button
- Support YouTube, Vimeo, and 1000+ video sites
- Download videos to import folder for PeerTube admin upload
- Show download status and video count

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-02-17 16:20:50 +01:00
parent 75b85080fa
commit 3150c65e99
5 changed files with 176 additions and 2 deletions

View File

@ -64,6 +64,13 @@ _Last updated: 2026-02-17 (v0.21.0 - Nextcloud LXC + WebRadio)_
### Just Completed (2026-02-17)
- **PeerTube yt-dlp Video Import** — DONE (2026-02-17)
- Installed yt-dlp in PeerTube LXC container
- Added RPCD methods: import_video, import_status
- LuCI UI section with URL input and download button
- Supports YouTube, Vimeo, and 1000+ sites
- Downloads to import folder for PeerTube admin upload
- **mitmproxy WAF Filters UI** — DONE (2026-02-17)
- Added new "WAF Filters" tab to mitmproxy LuCI interface
- Displays 10 filter categories: sqli, xss, lfi, rce, cve_2024, scanners, webmail, api_abuse, nextcloud, roundcube

View File

@ -68,5 +68,18 @@ return L.Class.extend({
object: 'luci.peertube',
method: 'configure_haproxy',
expect: { }
}),
importVideo: rpc.declare({
object: 'luci.peertube',
method: 'import_video',
params: ['url'],
expect: { }
}),
importStatus: rpc.declare({
object: 'luci.peertube',
method: 'import_status',
expect: { }
})
});

View File

@ -53,6 +53,15 @@ return view.extend({
}
promise = api.emancipate(domain);
break;
case 'import_video':
var url = args;
if (!url) {
ui.hideModal();
ui.addNotification(null, E('p', _('Video URL is required')), 'error');
return;
}
promise = api.importVideo(url);
break;
default:
ui.hideModal();
return;
@ -266,6 +275,61 @@ return view.extend({
E('hr'),
E('h4', {}, _('Import Video (yt-dlp)')),
E('p', {}, _('Download and import videos from YouTube, Vimeo, and 1000+ other sites using yt-dlp.')),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Video URL')),
E('div', { 'class': 'cbi-value-field' }, [
E('input', {
'type': 'text',
'id': 'import-video-url',
'class': 'cbi-input-text',
'placeholder': 'https://www.youtube.com/watch?v=...',
'style': 'width: 100%; max-width: 500px;'
})
])
]),
E('div', { 'class': 'cbi-page-actions', 'style': 'margin-bottom: 15px;' }, [
E('button', {
'class': 'btn cbi-button cbi-button-action',
'click': function() {
var urlInput = document.getElementById('import-video-url');
self.handleAction('import_video', urlInput.value);
}
}, _('Download Video')),
' ',
E('button', {
'class': 'btn cbi-button',
'click': function() {
api.importStatus().then(function(res) {
var statusText = res.downloading === 'true' ?
_('Download in progress...') :
_('No download running');
statusText += '\n' + _('Videos ready: ') + (res.video_count || 0);
if (res.files) {
statusText += '\n\n' + res.files;
}
ui.showModal(_('Import Status'), [
E('pre', { 'style': 'white-space: pre-wrap; max-height: 300px; overflow: auto;' }, statusText),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': ui.hideModal
}, _('Close'))
])
]);
});
}
}, _('Check Status'))
]),
E('p', { 'style': 'font-size: 12px; color: #666;' }, [
_('Supported sites: YouTube, Vimeo, Dailymotion, Twitter, TikTok, and '),
E('a', { 'href': 'https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md', 'target': '_blank' }, _('1000+ more')),
_('. Videos are saved to the import folder for manual upload via PeerTube admin.')
]),
E('hr'),
E('h4', {}, _('Logs')),
E('div', { 'id': 'peertube-logs' }, [
E('pre', {

View File

@ -254,6 +254,85 @@ method_configure_haproxy() {
json_dump
}
# Method: import_video (yt-dlp)
method_import_video() {
read -r input
json_load "$input"
json_get_var url url
if [ -z "$url" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "URL is required"
json_dump
return
fi
# Check container is running
if ! lxc-info -n peertube 2>/dev/null | grep -q "RUNNING"; then
json_init
json_add_boolean "success" 0
json_add_string "error" "PeerTube container is not running"
json_dump
return
fi
# Get videos path from UCI or use default
local videos_path
videos_path=$(uci_get main videos_path "/srv/peertube/videos")
# Create import directory inside container
local import_dir="/var/lib/peertube/storage/tmp/import"
lxc-attach -n peertube -- mkdir -p "$import_dir" 2>/dev/null
# Run yt-dlp in background, save to import directory
local logfile="/tmp/ytdlp-import-$$.log"
lxc-attach -n peertube -- /usr/local/bin/yt-dlp \
--no-playlist \
--format "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" \
--merge-output-format mp4 \
--output "$import_dir/%(title)s.%(ext)s" \
--write-info-json \
--write-thumbnail \
"$url" > "$logfile" 2>&1 &
local pid=$!
# Wait up to 5 seconds for initial response
sleep 2
json_init
json_add_boolean "success" 1
json_add_string "message" "Download started in background (PID: $pid)"
json_add_string "log_file" "$logfile"
json_add_string "import_dir" "$import_dir"
json_dump
}
# Method: import_status - Check import progress
method_import_status() {
local import_dir="/var/lib/peertube/storage/tmp/import"
local files=""
local count=0
if lxc-info -n peertube 2>/dev/null | grep -q "RUNNING"; then
files=$(lxc-attach -n peertube -- ls -la "$import_dir" 2>/dev/null | tail -10)
count=$(lxc-attach -n peertube -- find "$import_dir" -name "*.mp4" 2>/dev/null | wc -l)
fi
# Check for running yt-dlp processes
local downloading="false"
if lxc-attach -n peertube -- pgrep -f yt-dlp >/dev/null 2>&1; then
downloading="true"
fi
json_init
json_add_string "downloading" "$downloading"
json_add_int "video_count" "$count"
json_add_string "files" "$files"
json_dump
}
# List available methods
list_methods() {
json_init
@ -281,6 +360,11 @@ list_methods() {
json_close_object
json_add_object "configure_haproxy"
json_close_object
json_add_object "import_video"
json_add_string "url" ""
json_close_object
json_add_object "import_status"
json_close_object
json_dump
}
@ -327,6 +411,12 @@ case "$1" in
configure_haproxy)
method_configure_haproxy
;;
import_video)
method_import_video
;;
import_status)
method_import_status
;;
*)
echo '{"error":"Method not found"}'
;;

View File

@ -3,13 +3,13 @@
"description": "Grant access to PeerTube management",
"read": {
"ubus": {
"luci.peertube": ["status", "logs"]
"luci.peertube": ["status", "logs", "import_status"]
},
"uci": ["peertube"]
},
"write": {
"ubus": {
"luci.peertube": ["start", "stop", "install", "uninstall", "update", "emancipate", "live_enable", "live_disable", "configure_haproxy"]
"luci.peertube": ["start", "stop", "install", "uninstall", "update", "emancipate", "live_enable", "live_disable", "configure_haproxy", "import_video"]
},
"uci": ["peertube"]
}