- PVSM.RU - https://www.pvsm.ru -
Внимание. Хабр — не для политики. Пожалуйста, воздержитесь от обсуждения оной в комментариях.
В предверии первых выборов в России, в ходе которых все участки были оснащены веб-камерами, многие выражали желание записать для себя видео с камеры. Для этого предлагались разнообразные решения, от записи FRAPSом, до использования ffmpeg и так далее. Самым удачным, на мой взгляд, была утилита Qwertovsky [1], выложенная тут [2]
В данном небольшом топике я хотел бы предложить свое решение и вкратце напомнить, как вообще работает вся эта система, благо что завтра состоятся парламентские выборы на братской Украине, за ходом которых любой желающий может наблюдать на сайте vybory2012.gov.ua [3].
Итак, что следует знать:
Для каждой камеры раз в 15 секунд генерируется свежий плейлист, в котором содержатся прямые ссылки на последние 4 кусочка видео, длительность каждого кусочка — 15 секунд. Соответственно, раз в минуту плейлист полностью обновляется, а чанки продолжают быть доступны еще некоторое время.
Плейлист дублируется на нескольких серверах, доступен по ссылке вида http://server/variant.m3u8?cid=uid&var=orig и выглядит он примерно так:
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:6885
#EXT-X-TARGETDURATION:15
#EXT-X-ALLOW-CACHE:NO
#EXT-X-PROGRAM-DATE-TIME:2012-10-27T11:02:08Z
#EXTINF:13,
/segment.ts?cid=f0ffd596-aaa6-4601-9432-70d717dd666a&var=orig&ts=1351335728.24-1351335741.20
#EXTINF:11,
/segment.ts?cid=f0ffd596-aaa6-4601-9432-70d717dd666a&var=orig&ts=1351335741.20-1351335752.28
#EXTINF:11,
/segment.ts?cid=f0ffd596-aaa6-4601-9432-70d717dd666a&var=orig&ts=1351335752.28-1351335763.40
#EXTINF:14,
/segment.ts?cid=f0ffd596-aaa6-4601-9432-70d717dd666a&var=orig&ts=1351335763.40-1351335776.92
#EXTINF:11,
/segment.ts?cid=f0ffd596-aaa6-4601-9432-70d717dd666a&var=orig&ts=1351335776.92-1351335788.36
Ссылка вида /segment.ts?cid=f0ffd596-aaa6-4601-9432-70d717dd666a&var=orig&ts=1351335728.24-1351335741.20 в данном случае обозначает кусочек видео с камеры f0ffd596-aaa6-4601-9432-70d717dd666a и интервалом с 1351335728.24 по 1351335741.20 в несколько усложненном формате Unix time.
Периодическое, раз в минуту, распарсивание плейлиста и скачивание всех доступных кусочков даст нам в результате максимум информации с камеры, за исключением тех моментов, когда на стороне камеры будет исчезать доступ в Интернет. Например, как-нибудь так:
# -*- coding: utf-8 -*-
# vybory2012 (Proof of concept), yegorov-p
import urllib
import os
from time import strftime, localtime, sleep
import socket
import threading
#Адрес сервера syslog, куда сыпалась вся статистика
syslog_server='127.0.0.1'
syslog_port=514
#Корневая папка, куда будем складировать чанки
directory='dumps'
#Массив с id камер, их хешами и списком серверов, откуда можно тянуть чанки
cams=[
['563-1', "f0ffd596-aaa6-4601-9432-70d717dd666a",["82.207.0.3","82.207.0.3","82.207.0.3"]]
]
#обозначения уровней для сислога
LEVEL = {
'emerg': 0, 'alert':1, 'crit': 2, 'err': 3,
'warning': 4, 'notice': 5, 'info': 6, 'debug': 7
}
#процедурка, пишущая в сислог. Копирайты потеряны, сорри =(
def syslog(message, level=LEVEL['notice'], host=syslog_server, port=syslog_port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
data = '<%d>%s' % (level + 24, message)
sock.sendto(data, (host, port))
sock.close()
#Основная процедура
def cam_rip(num,hash,servers):
syslog('Recording cam %s at %s'%(hash, num), level=LEVEL['info'])
try:
os.mkdir('./%s/%s'%(directory,num))
except:
pass
#Запускаем бесконечный цикл
while 1:
try:
server=servers[0]
#Скачиваем текущий плейлист
page = urllib.urlopen("http://%s/variant.m3u8?cid=%s&var=orig"%(server,hash)).read()
#Если плейлист кошерен, выдираем ссылки на отдельные чанки и скачиваем их
if '/segment' in page:
for i in page.split('n'):
if '/segment' in i:
filename=strftime("%d-%b-%H-%M-%S", localtime(int(i[-13:-3])))
f=open('./%s/%s/%s.ts'%(directory,num,filename),'wb')
#syslog('Chunk %s saved'%(filename), level=LEVEL['notice'])
f.write(urllib.urlopen("http://%s%s"%(server,i)).read())
f.close()
else:
#В противном случае ругаемся в сислог и делаем ротацию сервера
syslog('No signal!Rotating server on cam %s at %s'%(hash,num), level=LEVEL['err'])
servers.append(servers[0])
del servers[0]
sleep(60)
except Exception,e:
syslog('Error on cam %s: %s'%(hash,e), level=LEVEL['err'])
servers.append(servers[0])
del servers[0]
try:
os.mkdir(directory)
except:
pass
#Запускаем кучу потоков для каждой из камер
for i in cams:
threading.Thread(target=cam_rip, kwargs={"num": i[0],"hash": i[1],"servers": i[2]}).start()
sleep(1)
syslog('System started.', level=LEVEL['notice'])
Запускаем данный скрипт, указав ему папку для складирования чанков и, опционально, адрес сервера сислога, куда будет сыпаться всяческая текущая информация.
Однако, мы обошли вниманием один момент — откуда взять исходные данные для плейлистов, а именно сервер и id камеры? Здесь стоит сделать небольшое отступление. Данная система успешно применялась на выборах в России, в частности, я при помощи вышеупомянутого питонового скрипта смог записать все камеры своего города. Однако, с тех пор произошли некоторые изменения в движке. Раньше все необходимые данные можно было получить даже не логинясь. Теперь же требуется сначала добавить камеру себе в избранное, после чего по адресу /account/channels?station_id=cid (где cid — id камеры) станет доступен файлик с хешами камер и ip-адресами серверов. Где-то в районе двух часов дня я решил собрать полную базу хешей и выложить ее в паблик, но сервера уже сейчас, еще до основной нагрузке периодически вываливают 502 ошибку, что осложняет процесс =) Из 32183 участков хеши доступны примерно с 5000, и понемногу эта цифра увеличивается.
В принципе, текущие данные можно получить, открыв нужную камеру и выполнив CorePlayer.instances.core_player_1.source.origin в Firebug или его эквивалентах, но так получится получить только текущий сервер (а он будет отваливаться, судя по опыту российских выборов).
В данный момент на камерах показываются заглушки, видимо украинские коллеги учли российский опыт, и решили не показывать будни школ, библиотек и общежитий.
Автор: PEgorov
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/18176
Ссылки в тексте:
[1] Qwertovsky: http://habrahabr.ru/users/qwertovsky/
[2] тут: http://habrahabr.ru/post/139292/
[3] vybory2012.gov.ua: http://vybory2012.gov.ua
Нажмите здесь для печати.