tangetools/youtube-lbry/youtube-lbry

146 lines
3.9 KiB
Bash
Executable file

#!/bin/bash
: <<=cut
=pod
=head1 NAME
youtube-lbry - Copy videos from YouTube to LBRY
=head1 SYNOPSIS
B<youtube-lbry> @lbry-channel https://youtube-url [https://youtube-url ...]
=head1 DESCRIPTION
B<youtube-lbry> downloads a YouTube video using B<youtube-dl>, and
re-publishes it in a channel on LBRY.
It tries to preserve title, description, thumbnail, upload date,
license, author, tags
=head1 EXAMPLES
=head2 EXAMPLE: Copy a single video
youtube-lbry @mytestchannel https://www.youtube.com/watch?v=KCzj6HOVOG4
=head2 EXAMPLE: Copy all PROSAs videos
playlist=UUe2zaWqk4k5WnwiYCOtP3tQ
lbry_channel=@PROSA
youtube-dl --get-id https://www.youtube.com/watch?list=$playlist |
parallel -uXj1 youtube-lbry $lbry_channel
=head1 AUTHOR
Copyright (C) 2021 Ole Tange,
http://ole.tange.dk and Free Software Foundation, Inc.
=head1 LICENSE
Copyright (C) 2012 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
at your option any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
=head1 DEPENDENCIES
B<youtube-lbry> uses B<youtube-dl>, and B<lbrynet>.
=head1 SEE ALSO
B<lbrynet>
=cut
copy_one() {
# E.g. channel_name="@mytestchannel"
channel_name="$1"
# E.g. https://www.youtube.com/watch?v=KCzj6HOVOG4
youtubeurl="$2"
tmp=$(mktemp -p "`pwd`" -d)
cd "$tmp"
# Get metadata in .json-format
youtube-dl --write-description --write-info-json --write-annotations -- "$youtubeurl"
# youtube-dl may download a .webm but convert it to mkv
# So we do not know the extension. Instead we use the newest
file_path="$(find "$tmp" -iregex \
'.*\(webm\|rm\|mkv\|mov\|mpg\|mpeg\|asf\|avi\|wmv\|flv\|mp4\|3gp\)$' \
-printf '%T@ %p\n' |
sort -n | tail -1 | cut -f2- -d" " | perl -pe 's/"/\\"/g')"
name="$(jq -r .fulltitle < *.json | perl -pe 'chomp;s/[^-a-z0-9]/-/gi')"
title="$(jq -r .fulltitle < *.json | perl -pe 'chomp;s/"/\\"/g')"
description="$(jq -r .description < *.json | perl -pe 's/"/\\"/g')"
# Not entirely true: Uploader could be someone else than Author
author="$(jq -r .uploader < *.json | perl -pe 'chomp')"
# One tag per --tags
tags_opt="$(jq -r .tags[] < *.json | perl -pe 'chomp; s/(.*)/--tags="$1" /')"
# Untested
languages_opt="$(jq -r .formats[].language < *.json |
grep -v 'null' |
perl -pe 's/(.*)/--languages=$1 /')"
license="$(jq -r < *json .license)"
thumbnail_url="$(jq -r .thumbnail < *.json | perl -pe 'chomp')"
release_time="$(jq -r .upload_date < *.json | perl -MHTTP::Date -nwle 'print str2time($_)' )"
lbry_publish() {
cat <<EOF > lbry.publish
lbrynet publish \
--bid=0.00001 \
--file_path="$file_path" \
--name="$name" \
--title="$title" \
--description="$description" \
--author="$author" \
$languages_opt \
$tags_opt \
--license="$license" \
--thumbnail_url="$thumbnail_url" \
--release_time="$release_time" \
--channel_name="$channel_name" \
--optimize_file \
--validate_file
EOF
bash lbry.publish >> lbrynet.out
}
if lbry_publish ; then
green="\033[48;5;78;38;5;0m"
reset="\033[00m\n"
printf "$green"
printf "The video should show up in lbry://$channel_name in 5 minutes."
printf "$reset"
rm -r "$tmp"
else
amber="\033[48;5;208;38;5;0m"
reset="\033[00m\n"
cat lbrynet.out
printf "$amber"
echo Publishing to LBRY failed.
echo See errors in "$tmp"/lbrynet.out
printf "$reset"
fi
}
export -f copy_one
channel_name="$1"
shift
parallel -uj1 copy_one "$channel_name" ::: "$@"