История соседа ч.3
Наткнулся на интересную статью, где описываются некоторые возможности, которые можно реализовать на Ростелеком домофоне:
https://habr.com/ru/articles/791602/
Как вы, возможно, помните из моих прошлых статей, у нас есть чат «попутчики» где люди ищут себе попутчиков для передвижения в Москву из области и обратно. И вот что я заметил. Очень часто в часы пик, люди фоткают очереди, чтоб уже на подъезде к остановке понять, а нужно ли двигать сейчас домой, может переждать или может даже выбрать самокат вместо маршрутки или такси. По счастливому стечению обстоятельств один из подъездов, оборудованный Ростелеком домофоном захватывает камерой прямо остановку и место за ней, где обычно и скапливается очередь. А значит можно, опираясь на вышеуказанную статью, добавить в чат кнопку «посмотреть очередь», чем я собственно и занялся.
И так для доступа конкретно к стриму камеры необходимо получить stream_token. Чтоб это сделать нам необходим BEARER_TOCKEN, его мы храним статично. Как говорил автор статьи выше — BEARER_TOCKEN живет до 1 года, что вполне устраивает нас. Раз в год можно заходить с акаунта любого пользователя, брать оттуда токен и снова год не знать бед. Собственно метод:
def getStreamTocken() -> str:
headers = {
"Authorization": config.BEARERTOCKEN
}
response = requests.get(config.AUTHRTCAM,
headers=headers)
data = response.json()
return data['data']['device']['video_data']['stream_token']
Отлично. теперь у нас есть токен для доступа к видео потоку. Сам видео поток приходит в websocket фрагментами. К сожалению я не разобрался что это за фрагменты. Декодирование полученных байтов из WS приводили только к таким картинкам:
результат
Поэтому я пошел другим путем. Видеопоток можно захватить (это также описано в статье, ссылку на которую я оставил выше) с помощью всем известного curl.
cURL — служебная программа командной строки, позволяющая взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
И здесь нас встречает 2 ограничения.
Первое — сам видеопоток имеет название файла очень длинное, что не пропустить cURL при сохранении.
Второе — видеофаил идет бесконечным потоком. Его нужно как-то остановить, например на 1 секунде скачивания. Иначе мы просто будем бесконечно загружать дорожку пока не кончится память.
Интересно что на моем Mac в терминале вполне работала такая реализация
curl --max-filesice 5000000 -o newname https://url.com
Однако в Ubuntu, на которой и крутятся все мои боты, оно не работало и, после 2х дней поисков и разговоров тет-а-тет с GPT-4 я все же нашел рабочее решение:
curl https://url.com | head -c 400000 > live.mp4
Конечно бывалые пользователи терминала уверенно сами бы до этого дошли. Но я не могу назвать себя таковым. Для остальных поясню что тут происходит
head -c 400000 — ограничивает размер файла в битах. я для своих нужд путем пробы и ошибок выставил именно 400000, так как это ровно 1 секунда видео потока.
> live.mp4 — указывает на новое имя файла для сохранения.
Собственно весь прикладываю код всего метода
def getVideo(*args) -> None:
message: Message = args[0]
oldMessage = bot.send_message(message.chat.id,
reply_to_message_id=message.id,
text="Загрузка...")
os.system("curl 'https:url&token=" +
getStreamTocken() +
"' | head -c 400000 > live.mp4")
bot.edit_message_text(chat_id = oldMessage.chat.id,
message_id = oldMessage.id,
text="Еще чучуть...")
videoMessage = bot.send_video_note(message.chat.id, open("live.mp4", "rb"),
reply_to_message_id=message.id,
protect_content=True)
if videoMessage:
bot.delete_message(oldMessage.chat.id, oldMessage.id)
os.system("rm live.mp4")
time.sleep(60)
bot.delete_message(videoMessage.chat.id, videoMessage.id)
bot.delete_message(message.chat.id, message.id)
принимает args, потому что я исторически использовал telebot, не асинхронный, поэтому для таких задач использую threads (потоки), так как функция потенциально может на пару секунд положить весь основной функционал.
Ниже удаляем фаил с сервера сразу после отправки, а через 60 секунд удаляем все упоминания о том что сообщение вообще было вызвано, чтоб не захламлять чат.
Видео отображается как белый экран на скрине из-за настройки protect_content=True
Спасибо за внимание, надеюсь моя третья попытка в написании подобных статей более удачна.