Превью-изображения с YouTube, Vimeo и ruTube

Строю очень интересный сайт, на котором можно создавать ресурсы и указывать ссылку на видео с одного из 3х популярных видео-хостингов: YouTube, Vimeo и ruTube.

Созданные страницы должны выводиться плиткой, с показом картинки от видео, причем, со своего сервера - чтобы не ждать ответа от удалённого. Задача осложняется тем, что существует минимум 8 вариантов указания ссылок на эти 3 сервиса:
https://www.youtube.com/watch?v=ITwNkwoc4J0
http://youtu.be/ITwNkwoc4J0
https://www.youtube.com/embed/ITwNkwoc4J0?rel=0

http://vimeo.com/55028438
http://player.vimeo.com/video/55028438?title=0&byline=0&portrait=0&badge=0&color=e1a931

http://rutube.ru/video/6fd81c1c212c002673280850a1c56415/#.UMQYln9yTWQ
http://rutube.ru/tracks/6032725.html
http://rutube.ru/video/embed/6032725
Это всё ссылки на один и тот же клип Rammstein - Mein Herz brennt (Piano Version). Не стоит забывать еще и про юзеров, которые обязательно вставят в форму "ссылку для блога", то есть - прям тег iframe со всеми свойствами, который отдаст сервис.


Заценить магию:

Вот исходный код моего класса, пользуйтесь на здоровье. Он абсолютно самодостаточен и не завязан на MODX, требуется только cUrl.

В ответ приходит массив содержащий или ключ error с ошибкой, или ключи со ссылками image и video. Если картинку достать не получается - будет подставлен дефолтный url. Все ссылки на видео-хостинги приводятся к единому виду.

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

Пример использования:
require 'videothumb.class.php';

$url = isset($_GET['url']) ? trim($_GET['url']) : '';

$class = new videoThumb(array(
	'imagesPath' => dirname(__FILE__) . '/images/'
	,'imagesUrl' => '/assets/video/images/'
	,'emptyImage' => 'assets/_empty.png'
));
$video = $class->process($url);

print_r($video);
Отправите ссылку через $_GET и в ответ получите массив с результатом и картинку в указанной директории.

Обновлено 17.08.13

Какое то время назад парсинг с rutube.ru поломался, видимо там что-то поменяли.

Следующая заметка
Обсуждаем miniShop 2.0
Предыдущая заметка
Новое сообщество MODX


Комментарии ()

  1. Виталий Воропаев 09 декабря 2012, 13:27 # 0
    Прекрасная работа. Я думаю многие оценят.
    1. Виталий Воропаев 09 декабря 2012, 13:32 # 0
      Думаю было бы не плохо дописать еще один тип работы класса. Создание серии превью, для последующего формирования слайдшоу видео.
      1. Александр Наумов 09 декабря 2012, 15:05 # 0
        Круто! Спасибо.
        Заметил что ссылки начинающиеся с https парсер не понимает, а Youtube в основном все такие.
        1. Василий Наумкин 09 декабря 2012, 16:21 # 0
          Добавил поддержку https в регулярки.
        2. Добряков Алексей 09 декабря 2012, 20:59 # 0
          шикарно мужик
          1. dr Del 13 декабря 2012, 12:33 # 0
            Полезная вещь.
            Можно еще в докрутить чтобы проглатывала адреса из мобильной версий (http://m.youtube.com/)
            1. seigiard@gmail.com 09 января 2013, 19:27 # 0
              http://www.youtube.com/user/SilkRoadTheatre#p/a/u/2/6dwqZw0j_jY 
              http://youtu.be/6dwqZw0j_jY
              http://www.youtube.com/watch?v=6dwqZw0j_jY&feature=youtu.be
              http://youtu.be/afa-5HQHiAs
              http://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGo
              http://www.youtube.com/watch?v=cKZDdG9FTKY&feature=channel
              http://www.youtube.com/watch?v=yZ-K7nCVnBI&playnext_from=TL&videos=osPknwzXEas&feature=sub
              http://www.youtube.com/ytscreeningroom?v=NRHVzbJVx8I
              Вот варианты ссылок, которые я нашел для YouTube.

              Регулярка простая:
              ^https?\:\/\/(www\.)?youtu(\.be|be\.com).*(\/|\?|=)([\w-]{11})((&|\?).+)?$
              Но у меня по проекту условие, что один урл в одной строке, поэтому где-то может не работать.
              1. d start 12 января 2013, 09:27 # 0
                Обращаю ваше внимание на то, что превью-картинки сохраняются на сервер, то есть достаются ровно один раз, затем можно использовать их как угодно. При инициализации класса можно указать пути для работы.
                Странно, но у меня не создаются картинки категорически, путь возвращает, а картинки нет в папке. Права на директории 777 выставил, всё равно пусто.
                1. d start 12 января 2013, 09:52 # 0
                  Нашёл в чём дело конкретно в моей ситуации
                  $class = new videoThumb(array(
                  'imagesPath' => dirname(__FILE__) . '/images/'
                  ,'imagesUrl' => 'assets/video/images/'
                  ,'emptyImage' => 'assets/_empty.png'
                  ));
                  при указании пути вида 'imagesPath' => dirname(__FILE__). '/images/'
                  Картинка записывается в core/cache/includes/elements/modsnippet/images, а путь возвращается как будто она записана в правильный каталог.
                  1. Василий Наумкин 12 января 2013, 10:02 # 0
                    Да, всё верно.

                    Лучше указывать
                    'imagesPath' => MODX_ASSETS_PATH . '/images/'
                    1. d start 13 января 2013, 10:04 # 0
                      В результате у меня получился вот такой вот сниппет:
                      <?php
                      require_once MODX_ASSETS_PATH.'components/videothumb/videothumb.class.php';
                      
                      // можно передавать и как параметр и через запрос 
                      if(empty($url))
                      	{
                      		$vurl = trim(@$_REQUEST['vurl']);  
                      	}
                      else{
                      		$vurl = $url;
                      	}
                      
                      $class = new videoThumb(array(
                          'imagesPath' => 'assets/video/images/'
                          ,'imagesUrl' => 'assets/video/images/'
                      ));
                      
                      $result = $class->process($vurl);
                      $modx->setPlaceholders(array(
                         'video'	=> $result['video']
                         ,'image'	=> $result['image']
                      ),'v.');
                      //Эту конструкцию пришлось сделать для того, что бы в чанках при листинге через getResources не "залипали" картинки. Почему то для всех постов кроме первого картинка выводилась одинаковая 0_о
                      if($return)
                      	{
                      		switch($return)
                      			{
                      				case 'video': return $result['video'];
                      				break;
                      				case 'image': return $result['image'];
                      				break;
                      			}
                      	}
                      У меня оно работает, насчёт красоты исполнения и\или ресурсоёмкости — увы и ах, пока ничего не тестировал, в данны момент учитывалась только работоспособность, что бы поднять проект до альфа-версии.
                      Если у Вас есть какие то советы по оптимизации, с радостью учту.
                      1. Василий Наумкин 13 января 2013, 11:10 # 0
                        Не понятно, что делает этот сниппет? Зачем он и выставляет плейсхолдеры, и возвращает url картинки\видео?

                        У меня, например, через форму отправлялся урл, для него получалась картинка и сохранялась на сервер, записывая свой адрес в ТВ ресурса. Ну а потом уже обычный вывод страниц, через getResources, с этими картинками.

                        А тут какая задача?
                        1. d start 13 января 2013, 11:54 # 0
                          У меня задача: есть раздел с мастерклассами, они в частности состоят из видео и тестового описания. Т.е. надо выводить видео с ютубы на самой странице и картинку в анонсе, для завлекухи.
                          Сниппет я обозвал getVideo, он из TV получает ссылку на ютубное видео.
                          Сниппет сохраняет резултаты в плейсхолдеры, что бы удобнее было на странице/в шаблоне пользоваться этими результатами.
                          В разделе выводится листинг анонсов. При этом случился трабл: почему то при вызове сниппета в чанке анонса картинка выставлялась только для первого анонса, а для всех последующих — назначалась картинка последнего поста. Т.е. плейсхолдеры закешировались, хотя я и вызывал плейсхолдер некешируемо — [[!+v.image]] и сам сниппет тоже [[!getVideo?url=`[[+tv.studioVideo]]`]]
                          Потому я сделал так, что бы сниппет мог возращать требуемое значение, а не сохранять его в плейсхолдер. Теперь вызов в чанке делается так:
                          [[!getVideo?url=`[[+tv.studioVideo]]`&return=`image`]]
                          и всё заработало.

                          1. Василий Наумкин 13 января 2013, 12:30 # 0
                            Выходит, у тебя каждый раз запускается сниппет, обрабатывает ссылку и потом клиент тянет картинку с youtube?

                            При том, что сниппет, на самом деле, сохраняет эти картинки на твой сервер. В общем, я бы добавил ТВ studioImage и переделал так:
                            // В чанке вывода списка указываем фильтр для пустого ТВ image
                            <img src="" alt="" title="" />
                            

                            Пишем сниппет, getImage:
                            <?php
                            // Инициализируем videoThumb один раз, в переменную класса MODX
                            if (empty($modx->videoThumb) || !is_object($modx->videoThumb)) {
                            	require_once MODX_ASSETS_PATH.'components/videothumb/videothumb.class.php';
                            
                            	$modx->videoThumb = new videoThumb(array(
                            		'imagesPath' => MODX_ASSETS_PATH . 'video/images/'
                            		,'imagesUrl' => '/assets/video/images/'
                            		,'emptyImage' => 'assets/_empty.png'
                            	));
                            }
                            // Получаем ресурс, у которого нет картинки в ТВ, он достанется из кэша, ибо его только что получал getResources
                            if ($res = $modx->getObject('modResource', $input)) {
                            	// Получаем ТВ с адресом видео
                            	$url = $res->getTVValue('studioVideo');
                            	// Получаем картинку
                            	$result = $modx->videoThumb->process($url);
                            	// Если нам вернулась картинка - сохраняем в ТВ и возвращаем
                            	if (!empty($result['image'])) {
                            		$res->setTVValue('videoImage', $result['image']);
                            		return $result['image'];
                            	}
                            	// Иначе пишем ошибку в лог и возвращаем картинку по умолчанию
                            	else {
                            		$modx->log(modX::LOG_LEVEL_ERROR, 'Не могу получить картинку по адресу ' .$url.', ошибка: '.$result['error']);
                            		return '/assets/video/images/_empty.png';
                            	}
                            }
                            

                            Таким образом, класс videoThumb инициализируется только раз и сниппет запускается только на те записи, у которых нет ТВ с картинкой. Ну а картинки потом получаются с твоего сервера. Так быстрее и логичнее.

                            Писал в браузере, не проверял — могут быть опечатки.
                            1. d start 13 января 2013, 13:00 # 0
                              Понял, спасибо. Сегодня попробую.
                              Подумал вот ещ сделать кастом Tv — Video. Как считаешь надо оно?
                              1. Василий Наумкин 13 января 2013, 13:01 # 0
                                Я бы сделал — чтобы хранить и выводить ссылки на видео в одном формате, а не как юзер ввёл.
                              2. d start 14 января 2013, 08:54 # 0
                                // В чанке вывода списка указываем фильтр для пустого ТВ image
                                <img src="" alt="" title="" />
                                Эээ, а фильтр тут где?

                                Вот так вызывать:
                                <img src="[[+tv.studioImage:empty=`studioImage:getImage`]]" alt="" title="" />
                                Пральна?
                                1. d start 14 января 2013, 09:08 # 0
                                  Почитал сниппет повнимательнее и сделал вот так:
                                  [[+tv.studioVideoImage:empty=`[[+id:getStudioImage]]`]]
                                  Завелось =)
                                  Спасибо за такое интересное решение
                                  1. Василий Наумкин 14 января 2013, 12:20 # 0
                                    Да, верно. Не знаю, куда у меня там вызов в чанке делся =(
                    2. Чикин Артур 08 марта 2013, 10:36 # 0
                      На основе этого кода будет написан полноценный снипет? было бы не плохо. В репозитории модекса нету подобных дополнений. А установка из коробки была бы кстати.
                      1. Roman Galaktionov 10 мая 2013, 15:47 # 0
                        Помогите, как быть?
                        Я переделал немного скрипт, чтобы url видео брался из текстового поля. В итоге мне выдает:
                        Array ( [video] => http://www.youtube.com/embed/yn6AovshrzE [image] => /assets/video/images/edb556c74bbe09be4b0bc93346fae53e.jpg ) 
                        1. Василий Наумкин 10 мая 2013, 16:38 # 0
                          И в чем заключается вопрос?

                          Ты не можешь взять из массива то, что тебе нужно?
                        2. Роман Шоу 17 августа 2013, 20:10 # 0
                          А не знаете есть ли что-то подобное для джумла или подскажите, как сделать, чтобы превьюшки генерировались автоматически?
                          1. Василий Наумкин 17 августа 2013, 20:29 # 0
                            Это самостоятельный класс, он не привязан к MODX.

                            Его можно использовать где угодно.
                            1. Роман Шоу 17 августа 2013, 21:33 # 0
                              А как сделать, чтобы класс при загрузке страниц сразу загружался и генерировал превьюшки?
                          2. болгов евгений 23 марта 2014, 20:39 # 0
                            Здравствуйте.Это сайт только для программистов?
                            1. Чикин Артур 23 марта 2014, 20:44 # 0
                              Это блог им. Василия Наумкина. Так что этот блог для абсолютно всех желающих его читать.
                              1. Василий Наумкин 23 марта 2014, 20:54 # +1
                                Вы зарегистрировались и можете читать и писать. Включаем логику:

                                1. Если этот сайт только для программистов — то вы программист и вас не должен интересовать этот вопрос.
                                2. Вы не программист, но вы здесь общаетесь, а значит сайт не только для программистов.
                                3. Вы программист и ищите сайт только для программистов, и не можете понять — такой ли этот сайт? Учитывая, как легко вы зарегистрировались — нет, не такой.

                                Задача решена — этот сайт не только для программистов.
                                1. Володя 23 марта 2014, 21:00 # 0
                                  Повеселил)))
                              2. болгов евгений 23 марта 2014, 21:02 # 0
                                OK! Я и есть «кто угодно». Данный класс очень удобный, но хотелось бы более разжёванной документации. Потому как не являясь программистом, довольно сложно понять глубокие мысли г.Безумкина.Не понятно как передать $Get['url'].например, И что её вообще надо передовать. Закинул класс в файл. В другом файле подключил. И что далее. Как вывести всё это дело «на экран».
                                1. Чикин Артур 23 марта 2014, 21:10 # 0
                                  Куда еще разжованее?! И так постоянно документацию пополняем да вылизываем до супер доступного состояния.
                                  Читайте и просвещайтесь: docs.modx.pro
                                  1. Василий Наумкин 23 марта 2014, 21:12 # +1
                                    Если не понятно, что такое $_GET, то нужно нанять программиста или купить книжку по PHP.

                                    Такой детcкий сад никто объяснять не будет.
                                  2. болгов евгений 23 марта 2014, 21:13 # 0
                                    Я так и думал, что програмисты.
                                    1. Чикин Артур 23 марта 2014, 21:17 # 0
                                      Я не программист, скорее сетевик по профессии (будущей) и верстальщик (хобби) который знает основы почти всех основных языков программирования.

                                      Но знать основы != быть программистом.
                                    2. болгов евгений 23 марта 2014, 21:24 # -4
                                      Я рад за тебя. Всё таки правильно говорят о вашем сообществе в инете. Одно большое раздутое тщеславие и самолюбие.
                                      1. Чикин Артур 23 марта 2014, 21:30 # +4
                                        Тебя тут никто не держит.

                                        В нашей группе есть минимальный порог, 1-ое это знание основ PHP и 2-ое это желание познавать MODX Revo. У тебя нет ни 1 ни 2 пункта. И еще и желание как то оскорбить. Так что можете не задерживаться. И в любой другой подобной группе вам скажут тоже самое.
                                        1. Василий Наумкин 24 марта 2014, 06:33 # +1
                                          Спасибо, что зашел — а то я тут уже больше месяца никого не банил.
                                          1. Чикин Артур 24 марта 2014, 06:55 # 0
                                            Кстати на счет банов. Я так понимаю система банов будет для каждого ресурса своя, но для id.modx.pro так как он на своем движке работает то у него будет общий бан на все домены?
                                            1. Василий Наумкин 24 марта 2014, 07:27 # 0
                                              Верно.

                                              Если накосячишь на modx.pro — отключен будешь от всего.
                                        2. Михаил 18 апреля 2014, 15:23 # 0
                                          Василий есть код на вывод видео на экран по ссылке?
                                          1. Василий Наумкин 18 апреля 2014, 17:30 # 0
                                            Обычно достаточно просто обернуть ссылку в iframe — специальный класс для этого не нужен.
                                          2. dimasik-nl 20 ноября 2014, 01:49 # 0
                                            Добрый вечер. Парни помогите плиз. Я на сайте создал страничку, где я буду выставлять таймлапсы свои и других пользователей с Ютуба и Вимео:http://www.timelapseart.com/tajmlapsy/
                                            Ролики показываются тамбами, при нажатии переходят в модальное окно. Проблема заключается в том, что в ютубе картинка добовляются, а вот с вимео вышел гемор, ни как не могу сделать так, чтобы при добавлении таймлапса ролика, автоматически добавлялась картинка(thumbnail) с Вимео
                                            Используемый код для Ютуба:
                                            // проверить на наличие файла, если его нет, то вставлять картинку напрямую с youtube
                                            // img.youtube.com/vi/bQVoAWSP7k4/0.jpg
                                            $filename=$modx->getOption('assets_url').'components/vidlister/images/'.$video['id'].'.jpg';
                                            if (!file_exists($filename)) {
                                            $filename=«img.youtube.com/vi/$videoId/0.jpg»;
                                            }
                                            $video['image'] = $filename;
                                            $video['idx'] = $idx; //index

                                            Спасибо за бушую помощь
                                            Добавление новых комментариев отключено.