This post is also available in: Английский
Для мультимедийных порталов, предоставляющих посетителям возможность просматривать продолжительный по времени видеоконтент (такой как полнометражные фильмы) может быть актуальной задача запомнить место, на котором пользователь остановил воспроизведение, чтобы в дальнейшем предложить ему начать просматривать это видео с той же секунды. В этой статье мы рассмотрим несколько способов того, как это можно сделать.
Эта задача была бы очень простой, если бы воспроизведение всегда прекращалось по нажатию кнопки «стоп» в плеере. Но в реальности выделенную кнопку останова в плеере обычно не делают, а к прерыванию просмотра может приводить целый ряд причин:
- пользователь ушел на другую страницу,
- пользователь закрыл страницу с плеером,
- браузер пользователя некорректно завершил работу,
- пользователь остался на странице с плеером, но видео не загружается из-за технических проблем с сервером или сетевым соединением пользователя.
Дадее подробно рассмотрим возможные варианты реализации функции запоминания последней позиции просмотра, чтобы при последующем воспроизведении можно было начать просмотр с момента прерывания.
События DOM onbeforeunload или onunload
События onbeforeunload и onunload возникают для объекта window соответственно до события onunload и, когда пользователь уходит со страницы. Пример обработки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <HTML> <head> <script> function closeIt() { return "Any string value here forces a dialog box to \n" + "appear before closing the window."; } window.onbeforeunload = closeIt; </script> </head> <body> </body> </html> |
Перед закрытием страницы мы имеем возможность в последний момент отправить текущую позицию видео на сервер.
Недостатки: поддерживается не всеми браузерами (например, Opera), необходимо использовать синхронный AJAX-запрос, работает не во всех случаях, перечисленных выше.
Периодическая отправка на сервер текущей позиции
Через определенные интервалы времени в ходе воспроизведения видео мы можем отправлять на сервер текущую позицию. Пример на ActionScript:
1 2 3 4 5 | setTimeout(function () { if (video.playing) { sendPosition(video.position); } }, 5000); |
В дополнение к этому для увеличения точности можно также отправлять текущую позицию во время возникновения различных событий воспроизведения: постановка на паузу, перемотка, буферизация.
Недостатки: приходится искать компромисс между точностью запомненной позиции и снижением нагрузки на сервер по числу запросов.
Анализ лог-файлов Flash Media Server-а
Adobe FMS ведет подробный access.log для всех событий воспроизведения видео, включая событие прекращения воспроизведения в независимости от причины, по которой оно произошло. Пример записи в access.log:
1 2 3 4 5 6 | #Version: 1.0 #Start-Date: 2011-01-17 00:01:13 #Software: Adobe Flash Media Server 4.0.0 r1121 x64 #Date: 2011-01-17 #Fields: x-category x-event date time x-pid c-ip c-client-id cs-bytes c-referrer sc-bytes x-sname x-spos sc-stream-bytes x-file-size x-file-length x-trans-sname x-status x-comment stream stop 2011-01-17 11:03:57 16877 94.25.145.221 4702111234508538223 3567 http://www.example.com/player_test/fl_player.swf?sid=4r01p81fvvooj20bumhggevu12&uniqid=4ac11015f655b9335fe246a8ed24ae55&uid=136 1378700 8ca9dc3d48cab6e5f8a8d42844c5c91d 5990 1210365 343845829 5111.269043 - 210 - |
При анализе лог-файла для целей данной статьи в первую очередь следует обратить внимание на события stream pause и stream stop, в которых содержится точка останова. А события connection connect и disconnect помогут отделить сессии просмотра, которые уже завершились, от тех, которые еще продолжаются в момент обработки лога. Группировать строки лог-файла, относящиеся к одной сессии просмотра можно по различным полям, главное, чтобы их сочетание было уникальным для каждой сессии. В FMS есть для этого специальное поле c-client-id, но полагаться только на него не стоит, так как его значение может повторяться для различных сессий. Чтобы получить по-настоящему уникальный идентификатор, вы можете сгенерировать его на стороне клиента и добавить к URL вызова плеера.
В логе помимо прочей полезной информации присутствует тип события, позиция воспроизведения, на которой возникло событие, имя файла контента. Любую дополнительную информацию, которой FMS сам по себе не располагает, можно передать в лог через поле c-referrer. В это поле записывается URL, который был использован для загрузки плеера, воспроизводящего контент. Такую информацию, как идентификатор пользователя, идентификатор сессии, различные признаки платного контента (цена, тариф и т.д.) вы можете закодировать в строке URL плеера в любом удобном для обработки виде. Наиболее простой и очевидный вариант — в формате строки параметров GET-запроса.
Достоинства: возможность получения точной позиции при любых причинах останова.
Недостатки: позиция в логах привязана не к воспроизведению, а к позиции буфера плеера, поэтому ее необходимо корректировать; данные появляются в БД портала с задержкой, необходимой для обработки лог-файлов.
Использование Web-сокетов
В том случае, если не используется Flash Media Server, или вообще не используется Flash Player для воспроизведения видео, мы можем сэмулировать поведение FMS, поддерживая постоянное соединение с сервером в ходе воспроизведения видео, по которому будет передаваться информация о текущей позиции. В случае обрыва этого соединения, который скорее всего произойдет при уходе со страницы, мы можем с достаточной точностью определить позицию воспроизведения, на которой это произошло и запомнить ее в качестве позиции останова видео.
Пример работы с web-сокетами с использованием библиотеки Socket.io. Клиентская часть:
1 2 3 4 | var socket = new io.Socket(); function playerSendEventCallback(position) { socket.send(position); } |
Серверная часть:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var http = require('http'), io = require('socket.io'), server = http.createServer(function(req, res){ res.writeHeader(200, {'Content-Type': 'text/html'}); res.writeBody('Hello world'); res.finish(); }); server.listen(80); var socket = io.listen(server); socket.on('connection', function(client){ client.on('message', function(message){ savePosition(message); }); client.on('disconnect', function(){ … }); }); function savePosition(position) { ... } |
Недостатки: технология web-сокетов относительно новая и пока еще не поддерживается всеми распространенными версиями браузеров.
Заключение
Единого идеального способа решения поставленной задачи не существует, у всех из них есть свои существенные недостатки. Поэтому в реальной работе для обеспечения максимального качества предоставления услуг необходимо применять сочетание из нескольких описанных выше способов.
ZSP4MAR7EA4N