Youtube

From Blue-IT.org Wiki

Revision as of 08:23, 12 January 2012 by Apos (talk | contribs) (So here we go)

Youtube upload script

Thanks to an article on the german website "Linux und ich" , I decided to make my own upload script. I makes heavy usage of the source code provide youtube-upload.py, a python script. It also uses the split-tool provided in the examples directory!

Legal notice

This script is given AS IS. I am not responsible for loss of data (which is really not what I want and not likely to happen). But furthermore I am not responsible, if your google data is hacked using an insecure network or given away your data otherwise or using the third party software youtube-upload used by this script.

Prerequisites

  • have an ogv video (gtkRecordMyDesktop), e.g myvideo_name.ogv
  • you like to convert and upload it to Youtube using Nautilus (or in batch mode in bash)
  • provide your Youtube account data (which are the same like for google) in the code of the script
  • login into youtube in your browser (this will open you video page, when the script finished)
  • prepare a file named e.g. myvideo_name.meta - if you like - in the same directory as the video with the following content:
TITLE="Your title here"
DESCRIPTION="Description here"
# Valid categories: Tech Education Animals People Travel Entertainment Howto Sports Autos Music News Games Nonprofit Comedy Film
CATEGORY="Category here"
KEYWORDS="Keywords (colon separated here)"

It will be used for uploading the file. If you don't have such a file, a new one will be created when you enter your data (you will be asked)

  • have split_video_for_youtube.sh in your path and youtube_upload.py somewhere (get it here: youtube-uploade at google code )
  • have a wrapperfile called youtube-upload in your path:
#!/bin/bash
python /wherever/is/youtube_upload.py "${@}"

in your path, and made them executable (chmod +x filename)!!!

  • have mencoder installed

This is a nautilus script, can be turned into normal script

Put the given script into

~/gnome2/nautilus-scripts

and make it executable.

chmod +x scriptname

Beeing a nautilus script it can be easily turned into shell script changing the line

cd "$NAUTILUS_SCRIPT_CURRENT_URI"

into

cd "$(pwd)"

This might be also handy for troubleshooting!!!

If you like to like to make everything without interaction, you can alter the last part of the script beginning with:

if [ -f ${MYBASENAME}.part*.${MYCONVTYPE} ]
then
# Converted video exists

delete it until the end and substitude it with:

[ -f ${MYBASENAME}.meta ] || set_youtube_metadata
split_it
upload_it

This way the script will run through without asking you.

So here we go

#!/bin/bash

# Convert any given Video to a youtube compatible format ... and upload it
# Uses https://code.google.com/p/youtube-upload/ to upload to youtube

#########################################################################################
# Edit to your need

# Create a file containing your youtube data, and chmod 600, so only you
# can read it. See an example in line 18.
# Probably later I will include a dialog.
MY_YOUTUBE_ACCOUNT_DATA_FILE="/home/${USER}/.youtube-account-data"

# Valid Youtube categories:
VALID_CATEGORY="Tech Education Animals People Travel Entertainment Howto Sports Autos Music News Games Nonprofit Comedy Film"

# Do not edit after this line
#########################################################################################
# Content of MY_YOUTUBE_ACCOUNT_DATA_FILE
YOUTUBE_EMAIL="myname@googlemail.com"
YOUTUBE_PASSWORD="secret_password"
YOUTUBE_CHANNEL="MyChannelName"
[ -f "${MY_YOUTUBE_ACCOUNT_DATA_FILE}" ] && source "${MY_YOUTUBE_ACCOUNT_DATA_FILE}"
[ -f "${MY_YOUTUBE_ACCOUNT_DATA_FILE}" ] || zenity --error --text "There is not Youtube account data!!!\n\nProvide a file ${MY_YOUTUBE_ACCOUNT_DATA_FILE}"
[ -f "${MY_YOUTUBE_ACCOUNT_DATA_FILE}" ] || exit 1

########################################################################################
## Change this for toggling beeing a bash-script or a nautilus-script
DEBUGMODE="${2}"
[ "$DEBUGMODE" = "--debug" ] && DEBUG=1
[ $DEBUG ] && zenity --info --title "DEBUG-MODE" --text "Running in debugging mode."

[ $DEBUG ] || cd "$NAUTILUS_SCRIPT_CURRENT_URI"
[ $DEBUG ] && cd "$(pwd)"


MYCONVTYPE="mkv"	  # Used by the split tool, don't change
MYFILE="${1}"
#MYFILE_ORIG=""
[ $DEBUG ] && zenity --info --title "DEBUG-MODE" --text "DEBUG:\n\nInputfile: \"${MYFILE}\"\nFiletype: \"$(file "${MYFILE}")\""

# Detox it - filename correction
MYFILE_CORRECTED=""
if which detox
then
	#MYFILE_ORIG="${MYFILE}"
	MYFILE_CORRECTED="$(detox -v "${MYFILE}" | grep -v "Scanning" | cut -d'>' -f2 | sed -e 's/ //g')"
	[ "${MYFILE_CORRECTED}" = "" ] || MYFILE="${MYFILE_CORRECTED}"
	[ $DEBUG ] && zenity --info --text "Detoxed filename in var MYFILE: ${MYFILE}"
else
	if zenity --question --text "<detox> is not installed.\n\nDo you like to install it first and then repeat?"
	then
		exit 1
	else
		MYFILE_CORRECTED="$(echo "${MYFILE}" | sed -e 's/\:/-/g' | sed -e 's/\&/_and_/g' | sed -e 's/,/_-_/g' )"
		mv "${MYFILE}" "${MYFILE_CORRECTED}" && sync
		MYFILE="${MYFILE_CORRECTED}"
	fi
fi
if echo "${MYFILE}" | grep -v grep | grep ".part001"
then
	MYFILE_CORRECTED="$(echo "${MYFILE}" | sed -e 's/.part001//g')"
	mv "${MYFILE}" "${MYFILE_CORRECTED}" && sync
	MYFILE="${MYFILE_CORRECTED}"
fi

VIDEOTYPE_IS_OK="false"
file "${MYFILE}" | grep -v grep | grep ".ogv: Ogg data"  && VIDEOTYPE_IS_OK="true"
file "${MYFILE}" | grep -v grep | grep ".ogg: Ogg data"  && VIDEOTYPE_IS_OK="true"
file "${MYFILE}" | grep -v grep | grep ".mkv: data" && VIDEOTYPE_IS_OK="true"
file "${MYFILE}" | grep -v grep | grep ".mp4:" && VIDEOTYPE_IS_OK="true"
MYTYPE=""
file "${MYFILE}" | grep -v grep | grep ".ogg: Ogg data"  && MYTYPE="ogg"
file "${MYFILE}" | grep -v grep | grep ".ogv: Ogg data"  && MYTYPE="ogv"
file "${MYFILE}" | grep -v grep | grep ".mkv: data" && MYTYPE="mkv"
file "${MYFILE}" | grep -v grep | grep ".mp4:" && MYTYPE="mp4"


if [ "${MYTYPE}" = "" ]
then
	zenity --error --text "Dateitypzuordnung inkorrekt. Wahrscheinlich konnte der Dateiname nicht gelesen werden"
	exit 1
fi

MYBASENAME="$(basename "${MYFILE}" .${MYTYPE})"
TITLE="Titel hinzufügen..."
DESCRIPTION="Beschreibung hinzufügen..."
CATEGORY="Howto"
KEYWORDS="Stichwörter (kommagetrennt)..."

############################################################################
# Split vidwo
VIDEO_COUNT=0
split_it() {
	
        if test split_video_for_youtube.sh ${MYBASENAME}.${MYTYPE}
	then
		echo "Files splitted ..."
	else
		if [ "${MYTYPE}" = "mkv" ]
		then		
			# no conversion, but move to special pattern ...
			mv "${MYBASENAME}.${MYTYPE}" "${MYBASENAME}.part001.${MYCONVTYPE}"

		        notify-send  "Konvertierung nicht notwendig" \
		                -i /local/share/icons/kino.png \
		                "Das Video ${MYBASENAME} wird jetzt hochgeladen."

		else
	  		# FFmpeg tries it best preserving the quality
			# If ffmpeg fails, mencoder will be used
			if ffmpeg -y -i "${MYBASENAME}.${MYTYPE}" \
				-vcodec mpeg4 -acodec libfaac -sameq \
				"${MYBASENAME}.part001.${MYCONVTYPE}"
			then
			        notify-send  "Konvertierung erfolgreich" \
			                -i /local/share/icons/kino.png \
			                "Das Video ${MYBASENAME} wird jetzt hochgeladen."
			else
				# Mencoder produces smaller files, but I had some troubles with audio synchronisation
				if mencoder ${MYBASENAME}.${MYTYPE} -o ${MYBASENAME}.part001.${MYCONVTYPE} -oac mp3lame -ovc lavc
				then
				        notify-send  "Konvertierung erfolgreich" \
			                -i /local/share/icons/kino.png \
			                "Das Video ${MYBASENAME} wird jetzt hochgeladen."
				else

				        notify-send  "Konvertierung fehlgeschlagen" \
			                -i /local/share/icons/kino.png \
			                "Das Video ${MYBASENAME} konnte nicht konvertiert werden!"

				zenity --info --text "Versuchen sie in einem Terminal:\n\nffmpeg -i ${MYBASENAME}.${MYTYPE} -vcodec mpeg4 -acodec libfaac -sameq ${MYBASENAME}.part001.${MYCONVTYPE}"
				exit 1
				
				fi
			fi
		fi
	fi

	VIDEO_COUNT=$(ls "${MYBASENAME}.part"*.${MYCONVTYPE} | wc | awk '{print $1}')
}

upload_it() {

COUNT=$VIDEO_COUNT
while ( [ $COUNT -gt 0 ] );
do

	UPLOAD_FILE=""

	if [ $VIDEO_COUNT -eq 1 ]
	then PART=""
	else PART=" - Part $COUNT - $VIDEO_COUNT"
	fi
	echo "Uploading ${COUNT} file(s) ..."

	youtube-upload 	--email="${YOUTUBE_EMAIL}" \
			--password="${YOUTUBE_PASSWORD}" \
			--title="${TITLE}${PART}" \
			--description="${DESCRIPTION}" \
			--category="${CATEGORY}" \
			--keywords="${KEYWORDS}" \
			"${MYBASENAME}.part"*${COUNT}.${MYCONVTYPE} | \
	zenity  --progress --auto-close --pulsate --no-cancel \
                --title "Lade hoch ..." \
                --text  "Lade ${MYBASENAME}${PART} auf Youtube hoch ..." && \
        notify-send  "Hochladen von Videodatei" \
                -i /local/share/icons/ktorrent.png \
                "Hochladen von ${MYBASENAME}.${PART} erfolgreich."

	if [ $VIDEO_COUNT -eq 1 ] 
	then
		[ - f "${MYBASENAME}.part001.${MYCONVTYPE}" ] && mv "${MYBASENAME}.part001.${MYCONVTYPE}" "${MYBASENAME}.${MYCONVTYPE}"
	fi

	COUNT=$(expr $COUNT - 1)
	echo "COUNT is: $COUNT"
done

sync

# If you like to delete the generated videos for upload, uncomment the following

# If the input was an mkv-file , don't delete it
 "${MYTYPE}" = "mkv" ] || rm -f ${MYBASENAME}.part*.${MYCONVTYPE}

# Channel
#exec firefox "http://www.youtube.com/user/${YOUTUBE_CHANNEL}/videos" &

# You have to be logged in to see this site:
exec firefox "http://www.youtube.com/my_videos?feature=mhee" &

}

set_youtube_metadata() {

	if [ -f "${MYBASENAME}.meta" ] 
	then
		source "${MYBASENAME}.meta"
	else
		echo "TITLE=\"${TITLE}\"" > "${MYBASENAME}.meta"
		echo "DESCRIPTION=\"${DESCRIPTION}\"" >> "${MYBASENAME}.meta"
		echo "# Valid categories: ${VALID_CATEGORY}"  >> "${MYBASENAME}.meta"
		echo "CATEGORY=\"${CATEGORY}\"" >> "${MYBASENAME}.meta"
		echo "KEYWORDS=\"${KEYWORDS}\"" >> "${MYBASENAME}.meta"
		
		source "${MYBASENAME}.meta"
	fi

}

edit_metadata() {

	[ -f "${MYBASENAME}.meta" ] ||  set_youtube_metadata
	[ -f "${MYBASENAME}.meta" ] &&  source "${MYBASENAME}.meta"
	
	TITLE="$(zenity --entry --text "Titel:" --entry-text="${TITLE}")"
	echo "TITLE=\"${TITLE}\"" > "${MYBASENAME}.meta"
	DESCRIPTION="$(zenity --text "Beschreibung:" --entry --entry-text="${DESCRIPTION}")"
	echo "DESCRIPTION=\"${DESCRIPTION}\"" >> "${MYBASENAME}.meta"
        echo "# Valid categories: ${VALID_CATEGORY}"  >> "${MYBASENAME}.meta"
	CATEGORY="$(zenity --text "Kategorie:\n\n${VALID_CATEGORY}" --entry --entry-text="${CATEGORY}")"
	echo "CATEGORY=\"${CATEGORY}\"" >> "${MYBASENAME}.meta"
	KEYWORDS="$(zenity --text "Stichwörter:" --entry --entry-text="${KEYWORDS}")"
	echo "KEYWORDS=\"${KEYWORDS}\"" >> "${MYBASENAME}.meta"
	
}


###################################
# Main
if [ "${VIDEOTYPE_IS_OK}" = "true" ]
then
	echo "Filecheck OK"
else
	zenity --info --title "Fehler" --text "Dies scheint keine \"${MYTYPE}\"- oder \"${MYCONVTYPE}\"-Datei zu sein! Bitte überprüfen.\n\nAusgabe \"$(file \"${MYFILE}\")\""
	exit 0
fi

# Edit metadata
EDIT_META="false"
if test -f "${MYBASENAME}.meta"
then
	source "${MYBASENAME}.meta"
	zenity  --question --title "Metadata" \
		--text "Do you like to edit THE EXISTING file containing the Youtube-Metadata?\n\nTitel: ${TITLE}" \
		&& EDIT_META="true"
else
        zenity  --question --title "Metadata" \
                --text "There is not Metadatafile yes. Do you like to edit containing the Youtube-Metadata? Otherwise default values are used." \
                && EDIT_META="true"
fi

if [ "${EDIT_META}" = "true" ]
then
	edit_metadata
else
	set_youtube_metadata
fi

# Check if a mkv already exists
MKV_EXISTS="false"
[ -f "${MYBASENAME}.part*.${MYCONVTYPE}" ] && MKV_EXISTS="true"
[ -f "${MYBASENAME}.${MYTYPE}" ] && MKV_EXISTS="true"

if [ "${MKV_EXISTS}" = "true" ]
then
# Converted video exists
	if zenity --question --title "Existierendes Video auf Youtube hochladen" \
		--text "Umwandlung war nicht nöti: Existierunde Datei ${MYBASENAME}.${MYCONVTYPE} jetzt auf Youtube hochladen?\n\nMetadaten:\nTitel: ${TITLE}"
	then
		split_it
		upload_it
	else
		exit 0
	fi
else
# Converted video does not exist

if zenity --question --title "Video konvertieren und auf Youtube hochladen?" \
	--text "${MYBASENAME}.${MYTYPE} in ${MYCONVTYPE} umwandeln und auf Youtube hochladen?\n\nTitel: ${TITLE}"
then

	[ -f "${MYBASENAME}.meta" ] || set_youtube_metadata

	split_it
	upload_it

fi

fi

Batch-convert videos with avidemux

Avidemux is a very handy tool. Sometimes you have a lot of files of the same type laying around and you like to apply all the same filters to them. I use it to convert the videos form my camera (mov) into a compatible format for e.g. Openshot (avi).

The solution is very simple. There is a tool called avidemux_cli (command line interface). It can use the project-files created with the Avidemux graphical user interface. Simply save your settings with Avidemux-GUI to a file with the ending ".proj" alongside with your videos and run the follwoing script.

Special version for a certain project

There are only some things to edit:

  • a folder name where to save the converted files
  • the name of the video filetype to be converted (here mp4)
  • the name of the output video, this MUST match the type given in avidemux
  • the exact name of the avidemuxproject-file

For the script to run you need to install avidemux-cli and avidemux:

sudo apt-get install avidemux-cli avidemux
#!/bin/bash
FOLDER="Converted"
IN_TYPE="mp4"
OUT_TYPE="avi"
PROJECT="convert_to_mjpeg.proj"

##########################################

mkdir -p $FOLDER

cat "${PROJECT}" | \
fgrep -v app.load  | \
fgrep -v app.clearSegments  | \
fgrep -v app.addSegment  | \
fgrep -v app.markerA  | \
fgrep -v app.markerB \
> "${PROJECT}.cli"

cat "${PROJECT}.cli"

BASE=""
for InputItem in *.${IN_TYPE}
do 
	#BASE="$(basename $InputItem .${IN_TYPE})"
	BASE="$(basename $InputItem)"
	avidemux2_cli --load  "$InputItem" --run "$PROJECT.cli" --save "${FOLDER}/${BASE}.${OUT_TYPE}" 
done

General purpose version

I also created a version for batch processing and general purpose:

#!/bin/bash

which avidemux2_cli > /dev/null || echo "Please install: sudo apt-get install avidemux-cli"
which avidemux2_cli > /dev/null || exit 1

[ "$4" ] || cat <<EOF

 USAGE: $(basename $0) 
		<OUTPUT_FOLDER_NAME> 
		<IN_TYPE OUT_TYPE> 
		<OUTPUT_FILETYPE> 
		<AVIDEMUX_PROJECT_FILE_NAME>

 e.g.

 $> $(basename $0) ConvertedFiles mp4 avi myavidemux.proj

EOF

[ "$1" ] || exit 1
[ "$2" ] || exit 1
[ "$3" ] || exit 1
[ "$4" ] || exit 1

FOLDER="$1"
IN_TYPE="$2"
OUT_TYPE="$3"
PROJECT="$4"
LOGFILE="conversion.log"

##########################################

mkdir -p $FOLDER

cat "${PROJECT}" | \
fgrep -v app.load  | \
fgrep -v app.clearSegments  | \
fgrep -v app.addSegment  | \
fgrep -v app.markerA  | \
fgrep -v app.markerB \
> "${PROJECT}.cli"

cat "${PROJECT}.cli"

BASE=""
ERROR="0"
for InputItem in *.${IN_TYPE}
do 
BASE="$(basename $InputItem .$IN_TYPE)"

cat <<EOF
#######################################################################
#######################################################################
## avidemux2_cli 
## --load  "$InputItem"
## --run "$PROJECT.cli" 
## --save "${FOLDER}/${BASE}.${OUT_TYPE}
##
EOF

avidemux2_cli --load  "$InputItem" --run "$PROJECT.cli" --save "${FOLDER}/${BASE}.${OUT_TYPE}" || ERROR="1"

cat <<EOF
#######################################################################

EOF

done

[ "$ERROR" = "1" ] && zenity --info --title "Conversion ended" --text "There have been ERRORS" 
[ "$ERROR" = "0" ] && zenity --info --title "Conversion ended" --text "OK"

Changelog

  • [Update] Changed converter from mencoder to ffmpeg due to audio sync problems - --Apos 01:49, 6 January 2012 (CET)
  • [Update] Major version update of script - --Apos 04:33, 6 January 2012 (CET)