Загрузка видео посредством YouTube API

Некоторое время назад по работе пришлось изучить и настроить работу сайта заказчика с YouTube, после этого для своего, как это теперь принято говорить, стартапа, я применил практически те же знания и умения. В этом небольшом посте я расскажу, как используя youtube api загружать видео файлы.

Оговорюсь сразу, что не стоит уделять большое внимание приведенному в посте коду – он написан специально для этого поста и несет скорее смысловую нагрузку для лучшего понимания. Весь код на этаком диалекте PHP :)

Шаг первый заключается в регистрации вас как обычного пользователя на сервисе youtube. Конечно, вы можете использовать существующую пару логин-пароль, но как мне кажется для удобства лучше зарегистрировать нового пользователя, в канале которого будет транслироваться загружаемое видео.

Шаг второй начинается с посещения страницы http://code.google.com/apis/youtube/dashboard/, где мы получаем свой ключ разработчика (Developer Key). На указанной странице нужно будет указать название вашего приложения, URL сайта с которого мы будем отправлять запросы и описание. Введя необходимые данные система сгенерируется для нас наш ключ, который представляет из себя последовательность символов вроде: AI39si5b05QIsObFU2_BSrPvyO6zC9Eu14BnDzKkhhIqHebS4PqE8o2AKigjP8gCaYTFblB8bpj8CkIWAUMF0vWBU5qykdmWjw.

Стоит отметить, что при отправке данных YouTube мы будем передавать в том числе два основных параметра X-GData-Client: <client_id>, где <client_id> — это собственно указанное название приложения, и X-GData-Key: key=<developer_key>, где как нетрудно догадаться <developer_key> — сгенерированный ключ. На этом этапе мы закончили подготовку и начинаем построение приложения.

Шаг третий начинается с изучения документации разработчика (http://code.google.com/intl/ru/apis/youtube/developers_guide_protocol.html), понять структуру документации — очень важно, потому что для людей не знакомых с системой организации документации у Google это изначально может показаться сложным. После того, как вы поймете, что и откуда – проблемы исчезнут.

Итак, у нас есть некоторые константы, которые будут использоваться везде и всюду, это:
  • API_KEY – девелоперский ключ
  • API_NAME – название приложения
  • YOUTUBE_EMAIL – регистрационный е-майл на YouTube
  • YOUTUBE_PASS – пароль для входа в ваш аккаунт на YouTube
  • YOUTUBE_USERNAME – имя пользователя на YouTube

Как и где, вы будете хранить эти константы – я не знаю, возможно это будут какие-то конфигурационные файлы, или константы, объявленные DEFINE – не суть, но стоит отметить, что эти данные будут нужны всегда и везде, поэтому постоянное дергание их из базы данных, думаю не самое лучшее решение.

Для начала корректной работы нам требуется получить значение еще одной константы – маркер аутентификации. Google предоставляет два типа аутентификации: Auth Sub и ClientLogin. Последний способ будет рассмотрен в рамках данной заметки – это позволит определять аккаунт пользователя, связанный с последующими запросами, именно поэтому нам нужно будет передать в последующих запросах логин и пароль.

Нам необходимо на URL www.google.com/youtube/accounts/ClientLogin отправить данные, которые позволят нас однозначно идентифицировать и предоставить маркер аутентификации. Ниже я приведу небольшой кусок кода, очевидно, что для тех, кто хочет использовать curl этот код станет более элегантным, но я предупреждал в самом начале, что код приводится только для ознакомления:

$eq = 'accountType=HOSTED_OR_GOOGLE&Email=YOUTUBE_EMAIL&Passwd=YOUTUBE_PASS&service=youtube&source=API_NAME;
if ($fp = fsockopen ("ssl://www.google.com", 443, $errno, $errstr, 20))
{
$request ="POST /youtube/accounts/ClientLogin HTTP/1.0\r\n";
$request.="Host: www.google.com\r\n";
$request.="Content-Type:application/x-www-form-urlencoded\r\n";
$request.="Content-Length: ".strlen($eq)."\r\n";
$request.="\r\n\r\n";
$request.=$eq;
fwrite($fp,$request,strlen($request));
while (!feof($fp))
$response.=fread($fp,8192);
fclose($fp);
}
preg_match("!(.*?)Auth=(.*?)\n!si",$response,$ok);
AUTH_TOKEN = $ok[2];


Итак, как мы теперь видим, мы получили положительный ответ от Google, где среди прочего был приведен маркер аутентификации, который сохранен в константе AUTH_TOKEN. Этот маркер нужно время от времени обновлять – я, к сожалению не нашел как долго маркер считается действительным, поэтому кроном раз в час получаю новый, который позже используется в работе.

Вот теперь мы полностью готовы к работе с YouTube.

Шаг четвертый – загрузка видео. Загрузка видео формально состоит из двух компонентов: отправки данных с последующим получением URL загрузки, и собственно загрузки видео. Для того, чтобы получить уникальный URL загрузки, куда собственно и стоит отправлять наши видео мы должны отправить на сервер данные, которые описывают видео: название, описание, теги и категорию.

Основной URL куда нужно отправлять данные для загрузки, редактирования, удаления, получения содержимого каналов и прочего, прочего – это gdata.youtube.com. Все данные передаются методом POST. Мы формируем запрос:

$data = "<?xml version='1.0'?>
<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:media='http://search.yahoo.com/mrss/'
xmlns:yt='http://gdata.youtube.com/schemas/2007'>
<media:group>
<media:title type='plain'>НАЗВАНИЕ_ВИДЕО</media:title>
<media:description type='plain'>ОПИСАНИЕ_ВИДЕО</media:description>
<media:category scheme='http://gdata.youtube.com/schemas/2007/categories.cat'>КАТЕГОРИЯ_ВИДЕО</media:category>
<media:keywords>ТЕГИ_ВИДЕО</media:keywords>
</media:group>
";


И после этого отправляем этот запрос:

if ($fp = fsockopen ("gdata.youtube.com", 80, $errno, $errstr, 20))
{
$request ="POST /action/GetUploadToken HTTP/1.1\r\n";
$request.="Host: gdata.youtube.com\r\n";
$request.="Content-Type: application/atom+xml; charset=UTF-8\r\n";
$request.="Content-Length: ".strlen($data)."\r\n";
$request .="Authorization: GoogleLogin auth=AUTH_TOKEN\r\n";
$request.="X-GData-Client: API_NAME \r\n";
$request.="X-GData-Key: key=API_KEY \r\n";

$request.="\r\n";
$request.=$data."\r\n";
socket_set_timeout($fp, 10);

fputs($fp,$request,strlen($request));
$response = fread($fp,3280);
fclose($fp);


Полученные от сервера данные сохранились в переменной $response. Ответ будет представлен в виде atom/xml, где нас больше всего интересуют два тега: — содержащий URL загрузки и , содержащий токен загрузки. Получить нужные данные мы можем, например так:

preg_match("!(.*?)!si",$response, $url);
preg_match("!(.*?)!si",$response, $token);


После этого, мы вполне можем сформировать форму для загрузки видео. Она будет выглядеть например так:
<form action="$url[1]?nexturl=URL_нашего_сайта_куда_передать_данные_после_загрузки" method="post" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="hidden" name="token" value="$token[1] " />
<input type="submit" value="go" />
</form>



После загрузки, если она прошла успешно сервер YouTube переправит браузер пользователя на URL_нашего сайта_куда_передать_данные_после_загрузки с уникальным кодом YouTube видео в адресной строке.

Ну, собственно и все, на этот раз. В этой своей заметке я намерено не затрагивал тему обработки ошибок, все это описано в документации, или познается эмпирическим путем. В следующий раз расскажу о проверке загруженного видео, редактировании и удалении.
+29
8 сентября 2009, 13:09
128
wolandino 10,9

комментарии (25)

0
crazyprog #
Вот меня все время интересовало, какой трафик и общий объем закаченных роликов они дают бесплатно?
0
wolandino #
Я не сталкивался с какими бы то ни было ограничениями. Скорее всего тут действуют те же правила пользовательского соглашения, что и для обычных пользователей.
+1
ainu #
А для вывода впоследствии закачанного видео обязательно использовать html вставку ютуба, или они выдают прямую ссылку на flv-файл для использования своим проигрывателем?
0
wolandino #
На выходе (вас переправит на указанную же вами страницу, помните?) вы получаете уникальный код вашего видео в ютубе.
Зная этот код вы можете уже использовать HTML-вставку ютуба, или как-то модифицировать ее. Но никакой прямой ссылки на flv вы не получаете.
0
dfg #
Для себя вижу только одну причину использовать свой проигрыватель – это внешний вид. Если это так, то внешний вид YouTube плеера можно подстроить под себя.
0
leoneed #
Меня интересует загрузка видео непосредственно РНР кодом с файла на диске сервера, а не из формы. Документация мне в этом не помогла ((( Есть у кого опыт, поделитесь, умоляю!
0
ruFog #
Полагаю, это невозможно
0
wolandino #
Возможно. Если соберусь с мыслями — напишу.
0
iexx #
А если попробовать как в форме выше, данные CURL-ом отправить. Вместе с token на урл, который сгенерил гугл.
+1
wolandino #
Нет, не совсем так. Тут есть описание на русском языке. code.google.com/intl/ru/apis/youtube/developers_guide_protocol.html#Direct_uploading.

Смысл примерно тот же, только меняется URL, куда мы отправляем данные и появляется ряд новых полей — вроде названия файла, двоичного кода загружаемого файла и так далее.

Если в примере выше все упирается в канал пользователя, потому что с его компа мы грузим напрямую на сервер Ютуб, то тут мы будем грузить со своего сервера.
0
iexx #
Ну так вообще все здорово тогда ;)
0
leoneed #
Поковыряем, поковыряем… Надо будет человеческий объект для этого дела накромсать.
0
qwertysx #
у меня в избранном поищите, ток там не пхп
0
Perez #
Спасибо, познавательно. Направлю сюда плагинмейкеров нашей маленькой CMS, может они сподобятся прикрутить это дело к системе :)
+1
iexx #
Я когда-то подобную задачу решал.
Какой смысл писать код выше, если уже давно как есть Zend_Gdata?
Этот класс давно реализует функционал с гуглёвыми сервисами. Если хотите могу пост написать ;)

framework.zend.com/manual/ru/zend.gdata.youtube.html
0
wolandino #
Вы знает про Zend_Gdata? Отлично! Я когда столкнулся с задачей в первую очередь тоже стал смотреть в сторону Zend_Gdata — благо в гугловской документации идет на него ссылка — но по определенным структурным особенностям нашей системы, я от него отказался.
–1
iexx #
Что же это за такие структурные особенности, при которых нужно писать свой велосипед? просветите, интересно просто

0
wolandino #
Оно заключалось в следующем: зачем использовать это, когда есть свой фреймворк, который проще дополнить одним небольшим классом (благо требовалось совсем немного — загрузка видео, его редактирование, удаление и проверка состояния на сервера)?
Написанный класс с успехом выполняет свои функции.
0
iexx #
Ну так а сам zend_gdata не сильно много и места занимает. Плюс ко всему я думаю можно выбросить из него кучу лишних классов.

На сайте zend лежит отдельный пак zend_gdata. Просто сэкономили бы время, только и всего ;)
0
wolandino #
Вот кстати отдельный пак я не видел, не копал так далеко. Если бы его не было — не было бы наверное и поста :)
+1
iexx #
На него ссылка вела с главной — Downloads ->Google Data APIs
видимо мне повезло больше)
framework.zend.com/download/gdata
0
ihoru #
Большое спасибо за лаконичность и ясность.
Уже попробовал, все работает. Очень доволен.
Одна поправка: в блоке, где отправляется post запрос на gdata.youtube.com, xml — документ не содержит закрывающий "\</entry\>".
0
Kolger #
Правильно ли я понимаю, что там есть ограничение на 2000 видео, а также видео не должно быть длиннее 10ти минут?
Если так, то придется писать свой велосипед с ffmpeg =/
0
jsmaximum #
А кто нибудь пробовал сделать загрузку видео напрямую на youtube, как здесь — code.google.com/intl/ru/apis/youtube/developers_guide_protocol.html#Direct_uploading?
0
aks1980 #
http://code.google.com/apis/gdata/docs/auth/clientlogin.html

The token remains valid for a set length of time, defined by whichever Google service you're working with. Typically, tokens remain valid for 2 weeks.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.