איך להוריד סרטי יוטיוב לצפיה אופליין באייפד/אייפון

כן, אני יודע שמזמן לא היה פה פוסט, תתבעו אותי ;).

אחד הדברים שאף פעם לא עובד כמו שצריך באייפון ובאייפד (ובאייפוד) זה YouTube. כלומר – יש ישום של אפל לצורך העניין, אבל החוויה לא מרנינה:
בדרך כלל לא תצליחו לראות סרטון בלי גמגומים, גם אם אתם משתמשים ברשת אלחוטית מהירה עם חיבור אינטרנט שמן וטוב.

לאחרונה אני צופה בדי הרבה משחקי סטארקרפט ביוטיוב, והפריע לי חוסר היכולת לראות את המשחקים על האייפד.
זה הביא לי רעיון:
מה אם נוריד מראש את הסרטונים, וניתן אותם לאייפד בצורת פיד RSS – ממש כמו שצופים בפוקסט וידאו – ככה שנוכל לראות אותם בלי להיות תלויים בחסדי מהירות התקשורת ליוטיוב?

אז בתור התחלה, הצצה למטרה של כל הפוסט הזה:
הנה פיד הרסס של הערוצים שאני מנוי עלהם ביוטיוב (Subscriptions).
את הפיד הזה הוספתי לאייטונז (כפודקאסט), ומאותו רגע הוא מוריד את הסרטונים ומסנכרן אותם לאייפד.

אז איך כל זה קורה?

הכל מתחיל בAPI הנתונים של יוטיוב, שמאפשר קבלת פידי RSS שונים ומשונים, כשהשימושי שבהם מבחינתי הוא פיד שמאפשר קבלת הסרטונים החדשים בערוצים שמשתמש מסויים מנוי עליהם:

http://gdata.youtube.com/feeds/base/users/omryy/newsubscriptionvideos

שימו לב ששם המשתמש שלי הוא חלק מהURL.
קל למדי לחלץ מפה את רשימת הURLים לסרטונים שמופיעים בפיד, למשל עם הסקריפט הזה:
[CODE]
GET "http://gdata.youtube.com/feeds/base/users/omryy/newsubscriptionvideos" | grep http://www.youtube.com/watch?v=[a-zA-Z0-9_\-]* -o | sort -u
[/CODE]
הסקריפט, בפשטות – מוריד את הפיד, מחפש בתוכו URLים שנראים כמו לינקים לסרטון ביוטיוב, ומבטל כפילויות שמופיעות מסיבה לא חשובה בפיד.

הצעד הבא הוא להוריד את הסרטים עצמם (הלינקים בפיד הם לינקים לצפיה ישירות ביוטיוב).
לשם כך נשתמש בכלי החביב במיוחד, youtube-dl,

הפקודה הבאה תוריד את הסרטון מהURL הנתון, ותשמור אותו בפורמט נחמד וברור שכולל את השם של מי שהעלה, וכן שם קובץ של הכותרת של הסרטים.
youtube-dl -w YOUTUBE_URL -o "%\(uploader\)s-%\(stitle\)s.%\(ext\)s"
אפשר לחבר את הפקודה הזו לפקודה שמחלצת את הURLים מהפיד תוך שימוש בxargs, אבל בחרתי להשתמש בGNU Parallel שמאפשר הפעלה של פקודה מסויימת כמה פעמים במקביל (בדומה מאוד לxargs, רק במקביל).

אז הפקודה השלמה להורדת הסרטונים שמעניינים אותי היא:
[CODE]
#!/bin/bash
source conf
pushd $YT_DOWNLOAD_DIR
GET "http://gdata.youtube.com/feeds/base/users/omryy/newsubscriptionvideos" | grep http://www.youtube.com/watch?v=[a-zA-Z0-9_\-]* -o | sort -u | $BIN_DIR/parallel -j $CONCURRENT_DOWNLOADS $BIN_DIR/youtube-dl -w {} -o "%\(uploader\)s-%\(stitle\)s.%\(ext\)s"
popd
[/CODE]

הסקריפט הזה (והבאים אחריו) משתמש בקובץ ההגדרות הבא:
[CODE]
BIN_DIR=/home/omry/youtube-rss/bin
YT_DOWNLOAD_DIR=/home/omry/youtube-rss/download
CONCURRENT_DOWNLOADS=20
RSS_WEB_DIR=/home/omry/www/youtube-rss.firefang.net
RSS_BASE_URL=http://youtube-rss.firefang.net

# Delete older than X days
DELETE_OLDER=14
[/CODE]
עד פה, הכל טוב.
הפקודה הזו תוריד רק קבצים חדשים שלא הורדו כבר (הדגל -w).

כשניסיתי להעלות לאייפד את הקבצים האלו, שמתי לב שהוא החליט לדלג על חלק גדול מהם.
מסתבר שכל הקבצים שדולגו היו ברזולוציה של HD מלא (1920X1080).
אוקיי, אז זה הדבר הבא שצריך לתקן.
בהתחלה חשבתי להשתמש בffmpeg – שהיא הפתרון המקובל לקידוד קבצי וידאו.
הבעיה היא שצריך לקמפל גרסא שלה שתומכת בH264 (הקידוד שמתאים למכשירי אפל), ושבאופן כללי די קשה לגרום לה לעשות מה שאתם רוצים.
אחרי המשך חפירות מצאתי את Handbreak שהיא תוכנה (בקוד פתוח כמו כל שאר הדברים בפוסט הזה) שתפקידה בחיים הוא לקודד סרטונים לאייפוד, אייפון אייפד ושאר חברים בצורה מאוד פשוטה.
Handbreak מגיעה עם ממשק GTK שלא ממש עניין אותי, ועם שורת פקודה שמאוד עניינה אותי.
אגב, היא משתמשת בlibavcodec מבית היוצר של מפתחי ffmpeg.
לעניינינו, הפקודה לקידוד סרטון לפורמט אייפד היא :
[CODE]
HandBrakeCLI -Z iPad -i input_file -o output_file.mp4
[/CODE]
לא יכול להיות יותר פשוט מזה.

התהליך עצמו יכול לקחת די הרבה זמן, תלוי באורך הסרט ובעוצמת העיבוד של המחשב שלכם.
Handbreak מספיק מוצלחת כדי להשתמש בכל הליבות שלכם (אפשר לומר לה להשתמש במספר מסויים אם רוצים) ולרוץ בעדיפות נמוכה כדי לא לחנוק תהליכים אחרים.

השתמשתי בתסריט bash קטן כדי לעבור על הקבצים שירדו, ולקודד לספריה חדשה קבצים עם אותו שם אם הם כבר לא נמצאים שם.
[CODE]
$ cat encode_new.sh
#!/bin/bash
source conf
for file in `ls -1 $YT_DOWNLOAD_DIR/*.mp4 $YT_DOWNLOAD_DIR/*.flv $YT_DOWNLOAD_DIR/*.video`
do
base=`basename ${file%.*}`
ipad=${RSS_WEB_DIR}/${base}.mp4
if [ -f $ipad ]
then
echo "Skipping $ipad"
else
$BIN_DIR/HandBrakeCLI -Z iPad -i $file -o $ipad
touch -c -r $file $ipad
./update_feed.sh
fi
done
[/CODE]

אחרי כל קובץ שמקודד, הסקיפט update_feed.sh נקרא.
סקריפט זה משתמש בתוכנית ג'אווה קטנה שכתבתי שמכינה קובץ RSS על בסיס ספריה עם סרטוני וידאו.
לבסוף, נשאר רק למחוק קבצים ישנים יותר מ14 יום כדי למנוע התפוצצות, ולהריץ את כל העסק פעם ביום או משהו עם CRON.

[CODE]
$ cat delete_old.sh
#!/bin/bash
source conf
find -mtime +$DELETE_OLDER -exec echo rm $YT_DOWNLOAD_DIR/{} $RSS_WEB_DIR/{} \;
[/CODE]

אפשר להוריד את כל העסק מפה, שימו לב שזה כולל את HandBreak בגרסאת AMD64 ללינוקס, אבל אפשר להוריד מהאתר שלהם גרסאות אחרות.

לסיום, הנה סרטון סטרקראפט מצחיק: