Скачиваем видео в формате m3u8
На днях у меня появилась потребность сохранить видео лекции с некоторого сайта, которой такой функциональности не представляет, а причиной этой необходимости послужило то, что после определенного времени с момента оплаты видео становится не доступным.
Анализ
Первое что пришло мне в голову это записать видео с экрана, например через QuickTime, но в таком случае нужно все их просмотреть а это по времени достаточно долго и этот вариант мне не понравился.
Следующим шагом было исследовать html код страницы, и там я нашел интересную ссылку:

Далее я попробовал подставить эту ссылку в адресную строку браузера и в результате скачался файл master.m3u8 следующего содержания:
Как можно увидеть этот файл содержит еще набор ссылок, и судя по их названию они обозначают разрешение видео, которое загружается.
Я решил посмотреть что из себя представляет файл 720.m3u8, для этого я его скачал, перейдя по соответствующей ссылке:
Если присмотреться внимательней то можно увидеть что все ссылки содержат *.ts, после того как я их скачал, оказалось что это как раз куски данного урока.
После небольшого поиска что-же такое m3u8 файл, я выяснил, что это формат для хранения плейлистов.
Теперь был вопрос как же его сохранить локально.
Сохранение видео из m3u8
Первое что я нашел в Интернете предлагало это сделать через VLC. Для этого нужно зайти в Файл -> Конвертировать/Передавать , после чего можно увидеть следующее окно:

В указывается исходный файл плейлиста, профиль сохранения и выходной файл. После чего нажимается кнопка Сохранить и процесс начинается (надо отметить, что процесс не быстрый).
Альтернативное сохранение
После того как таким способом я сохранил пару видео, я начал думать как оптимизировать процесс. Тут меня посетила мысль, что можно просто попробовать скачать все эти маленькие файлы и объединить их в один.
Для этого я написал небольшую утилитку на Go, для обработки файла *.m3u8 и объединения всех маленьких кусков из него в один файл.
Алгоритм работы ее достаточно прост: сначала я перехожу по заданной ссылке на m3u8, затем построчно обхожу его и если строка содержит URL кусочка, я скачиваю его и результат сразу пишу в выходной файл.
Код который это делает следующий:
Функция downloadFilePart отвечает именно за скачивание файла и вывод его в байтовый массив:
Такой метод полностью себя оправдал и оказался самый быстрый.
Заключение
В конечном счете я не только скачал все нужные лекции, но еще и создал утилиту для скачки и сохранения *.m3u8 файлов.
Скачиваем потоковое видео
В посте о скачивании видео без плагинов ( https://pikabu.ru/story/kak_skachat_kontent_s_lyubogo_sayta_. ) у многих возникли вопросы что делать с потоковым видео? Свой способ я проверял на таких онлайн-кинотеатрах как Б**кино и Г**онлайн, на других должен работать тоже.
Все действия производились в Опере, для Хрома все аналогично.
Для начала нам надо получить ссылку на .m3u8 файл. Для этого открываем страницу с фильмом. Нажимаем Ctrl+Shift+J и открываем вкладку Network. Далее запускаем воспроизведение. Ждем пока пройдет реклама и начнется фильм. В поиске вбиваем .m3u8. Находим два файла. Нам нужен тот, который больше размером (второй). Копируем его адрес.

Далее нам нужен VLC Media Player. Открываем его. Медиa -> Открыть URL ( или просто Ctrl+N). Вставляем ссылку на наш .m3u8 файл. Далее возле кнопки Воспроизвести стрелка вниз -> Поток

Далее на вкладке «Настройка вывода» нажимаем добавить и выбираем куда сохранить видео.


И в конце нажимаем кнопку «Поток»

Теперь ждем пока синяя строка дойдет до конца, и можно смотреть фильм.

не понял, что за сайты. но заходить туда почему-то и не хочется.
Я пользуюсь youtube-dl для всего этого. На убунте выглядит так:
sudo apt install youtube-dl
youtube-dl <Тут ссылка на страничку с видео>
Консольная утилита поддерживает кучу сервисов от ютуба до порнхаба, в том числе стриминговые сервисы (да, типа чатурбейта=) и даже какие-нибудь там всякие городские уличные камеры наблюдения будет скачивать. Я упомнул, что эта штука умеет целиком плейлисты качать?
Для винды есть портабельный экзешник. Ну а кому интересно, то в сущности это питоновская библиотека с кучей возможностей.
Тулза, кстати, получает кроме потока и метаданные, правильно (в том числе по шаблону) называет файл, умеет складывать рядом json со всей полежзной инфой о ролике.
Кто любит командную строку и терминал так же как я, тот оценит.
Да, всё руки не доберутся никак сделать чат-бота на основе этой либы, который бы возвращал прямую ссылку для скачивания взамен ссылки на страницу. Для хитрожопых случаев можно проксировать поток через пайпы. Корчое, пойду-ка я на хабр с этим. простите
Я проще поступаю. Сам пользуюсь Opera и поставил удобный плагин Flash Video Downloader. Скорей всего он делает тоже что описал ты, но мне он сразу при старте видео в миниокне даёт ссылку на скачивание, при нажатии начинает скачивать через загрузчик Opera.
P.S. Он пока меня ни на одном сайте не подводил. Для друга могу сказать что и на «тех» сайтах тоже работает))).

не понимаю в чем проблема взять и скачать фильм ?
Есть более извращенные способы отображения видео, я уже писал это в вашем прошлом посте, например сервис netu.tv позволяет хранить видео которое в последствии сложно будет скачать, m3u8 там просто нет, куски видео динамически подгружаются с помощью JS, формат фрагментов изменен и выглядят они примерно так: . /videos/2017/12/29/1514535491uuvp4.mp666Frag2Num1, где mp666Frag2Num1 заменив на mp4 получим кусок видео. Автоматизировать это конечно можно, но нужно либо использовать более гибкий софт, либо писать собственный грабер.
Я привел просто пример сервиса, а таких видео с каждым днем все больше и больше.
Многоходовочка
У жены была квартира, но она в ней не жила, а сдавала. Сейчас решили ее продать и новые покупатели очень обрадовались наличию жильцов, так как тоже хотели использовать ее под сдачу и попросили никакой аренды с ними не расторгать. Меня не покидает ощущение помещика начала 19 века, что мы продали не только землю, но и крепостных.
Заместитель председателя Государственной думы дал народу возможность предложить законы, но всем плевать

Это Чернышов Борис Александрович, важный член государственной думы, и он предложил пикабушникам самим накидать идей для новых законопроектов, чтобы улучшить нашу жизнь. Регистрация на встречу с пикабушниками + сбор предложений по законопроектам на осеннюю сессию Госдумы Но всем ПОХРЕН, ну вот абсолютно, у чувака 300 подписчиков за первый пост набралось, а плюсов под следущим постом 103. И что я вижу под вторым постом, абсолютно не реализуемые предложения по типу: давайте новое министерство сделаем с нуля. Лично я первый раз вижу чтобы какой-то важный член (государственной думы) пришёл на ресурс обычных людей, где в основном развлекательный контент, и сам не через 3 лиц писал людям
И вот сегодня, он под комментом какого-то чувака уверенного что тут нету никаких депутатов, #comment_283159240 написал 3 людям чтобы они проверили почту. ТРËМ КАРЛ. Один из них я, я если честно когда заявку подавал думал будет там человек 20-30 посижу послушаю умных людей. Я то в законотворчестве не силён, максимум могу чью-то идею говном полить, но это на пикабу в момент регистрации выдают вместе с 49,5. А теперь оказывается я там буду 3 по тупости, это ни в какие ворота. Мужики (и мужичессы) поднимите пост пожалуйста, пусть пикабутяне подтянутся, я не хочу там сидеть позорится один.
upd встреча, онлайн можно с компа на ней присутствовать, как на неё попасть есть в посте ссылку на который я вставил, там заявка, в ней три или 4 поля, имя ник на пикабе и почта. Вроде всё. Мне ссылка на почту пришла, я не переходил ещё, домой приду посмотрю. Ссылка на какой-то sba Yandex. Ссылку не кину хрен знает этих депутатов возьмёт и отменит всё нахрен
Финалистка "Мисс Англия" участвует в конкурсе без макияжа. Привет всем нашим "мисс"

А в Дагестане нельзя в шортах
В Москве задержали мужчин, требовавших от пассажирки метро снять никаб и «носить нормальную одежду»
Пострадавшая Елизавета Барановская подала заявление в Следственный комитет с просьбой завести дело по статьям о возбуждении ненависти по религиозному признаку и оскорблении чувств верующих, сообщила адвокат Аза Алиева.
1 сентября в социальных сетях распространилось видео, снятое Барановской. На видео один из пассажиров московского метро говорит девушке о том, что в стране идет мобилизация, а «русских пацанов на СВО убивают».
После этого в разговор вмешался другой пассажир, спросивший, мужчину, что он хочет от девушки. «Я хочу, чтобы она сняла [никаб] и нормальную одежду носила. Она скрывает лицо, у нас это террористическая угроза может быть», — ответил мужчина.
Видеозвонки без наушников
А можно как-то внести дополнение в Коран о запрете аудио и видеозвонков без наушников. Достали!

Развитое общество

Ответ Umacka в «Непривлекательные женщины намного более требовательные»
Обожаю такое. Сначала девушка пишет в анкете то, что отсекает 99% читающих эти анкеты, а потом жалуется, что ей почему-то пишут исключительно спамеры, гринданы, многонационалы, дикпикеры и просто долбоёбы, думающие исключительно нижней головой. И в комментариях хор точно таких же девушек с точно такими же жалобами и искренним непониманием, почему же так происходит. Наверное, просто нормальные мужчины кончились, да.
У меня есть очень сильное подозрение, что «общение и дружба», которых женщины ищут на сайте знакомств, в их представлении должны идти по тому же сценарию, что и полноценное знакомство, только чтобы мужчина не обольщался насчёт возможности отношений в дальнейшем.
Внимание, вопрос: а нахера это мужчинам?
Мужчина идёт на сайт знакомств с целью найти себе девушку. Неважно, на потрахаться пару раз или с прицелом на полноценные серьёзные отношения. Неважно даже, долбоёб он или вменяемый. Важно то, что он ищет на сайте знакомств именно девушку, то есть партнёршу. А если в целях знакомства девушки стоит только «общение и дружба», это считывается как полное отсутствие перспективы стать её парнем, а следовательно, и отсутствие смысла начинать общение. Именно поэтому «социальный эксперимент» @Ines.MM принёс такие результаты: #comment_283112116. Когда в анкете читаешь про поиск секса на один раз, это привлекает внимание и подталкивает задать вопрос, потому что такой поиск для женщины нехарактерен. Когда в анкете читаешь про поиск общения и дружбы, желания написать это не вызывает вообще никакого. А вот гринданы, дикпикеры и иностранные специалисты будут таким женщинам писать про писку ебат и рассылать непотребство, потому что им искренне насрать, что написано в анкете. Они это всё даже не читают, они тупо пишут всем.
Предвижу возмущение дам. «А что, с женщинами нельзя просто общаться и дружить?!» — можно. «А что, мужчинам не нужны общение и дружба?!» — нужны. Только мужчины идут на сайты знакомств не за этим.
И ещё один важный момент. Если вы хотите, чтобы мужчины, которые о вас не знают примерно ничего, интересовались в общении именно вами как человеком, то я вас разочарую: это отправная точка для интереса к потенциальной партнёрше, а вы со своей целью «общаться и дружить» в этом качестве бесперспективны. Для общения и дружбы нужны другие отправные точки. Один и тот же парень может пройти мимо вашей анкеты для «общения и дружбы» на СЗ, а через пару часов мило общаться с вами же в сообществе любителей фантастики или в гильдии в каком-нибудь World of Warcraft. Почему? Потому что на сайт знакомств он пришёл искать девушку, а в сообщества и в WoW — пообщаться, хорошо провести время, потрындеть про ваху с гарепотером и в рейде повасянить. И вы с ним можете это друг другу дать. И это как раз имеет шансы стать началом дружбы.
Поэтому если вы читали всего Толстоевского, Сальватолкина и Азиммонса, цитируете обе Эдды наизусть, знаете, чем дестреза отличается от болонской школы, можете сходу накидать пять рабочих билдов для тифлинга-барда и почти не сливаете мид, хотите завести новых друзей и не ищете себе партнёра — идите в тематические сообщества, паблики вконтакта, телеги, дискорды и иже с ними. Я искренне не понимаю, нахуя на СЗ пытаться найти кого-то для «общения и дружбы». Хотя, может быть, вам просто нравится коллекционировать сообщения от долбоёбов и дикпикеров и страдать, что «нормальных мужчин» больше нет.

Пост единственному подписчику
Дорогим гостям когда приходят в гости, всегда готовлю Бурятские Буузы.
Угощайся буузами и чаем с молоком мой единственный дорогой подписчик.

Устрани случайность

Ты где был?

Сосислон
Мальчики,они похоже всегда мальчики(дети) ,даже если им уже полтинник .Увидев, тут на сайте, Сосислона,муж загорелся: давай сделаем . Не вопрос ,было бы желание и вот ОН

Собери пять в ряд

Мама-сокол устроила себе гнездо в оконном ящике
Кто не понял, он упырь

Ответ на пост «Яндекс контора новоязов»
Небольшое пояснение людям, не понимающим, почему в наших заведениях подают или продают «не наши» блюда. Не ради срача, а дискуссии для.
Вот это макароны с сыром. Отварные макароны, посыпанные тёртым сыром. Вкусная штука, если в вашей институтской столовке не работает «мишленовский фьюжн шеф», решивший, что бахнуть на макароны колбасный сыр будет верхом изыска.

А вот это макнчиз. Чисто технически, тоже макароны с сыром. Но вообще, это макароны в сливочно сырном соусе. В идеале — присыпанные дополнительно сверху сыром и подрумяненные в духовом шкафу. По сути — это ближе к запеканке.

Вот это митболы. Их готовят из мяса, без добавок типа хлебного мякиша. И запекают в духовке без масла.

А вот это тефтели. Их чаще всего готовят в соусе. И в них не удивительно обнаружить хлебный мякиш или рис.

А вот это фрикадельки. Их чаще всего варят. Зато не добавляют в фарш всякий балласт.

Конечно, люди изгаляются кто во что горазд, и могут хоть на мангале их готовить. Но у блюда есть изначальное название. И классическое приготовление.
Но погнали дальше.
Вот это чай с лимоном. Если вы пойдете в столовую\кафе\ресторан и закажете «чай с лимоном» вам принесут горячий чай и лимон в качестве добавки.

А вот это айс ти. Он же «чайный лимонад». Сладкий чайный напиток с разнообразными добавками, который пьют холодным. В идеале со льдом.

Вот это кекс. Его пекут из плотного теста. Которое надо месить. По канону, кекс делают без начинки за исключением вмешиваемых в тесто включений типа изюма и орехов. Он всегда сладкий. «Кекс» это «сладкий, сдобный хлеб»

А вот это маффин. Его делают из заливного теста. Он мягче. И его часто делают с начинкой.
Кроме того маффин бывает, хоть с беконом, хоть с цветной капустой. То есть, это не обязательно сладкая булочка. Это закусочная булочка.

Сладкий маффин с шоколадной начинкой.

Закусочный маффин с беконом и яйцом.
Вообще в разборках вида «А сфига ли начали называть кекс маффином?» нет правых. Потому что более исконно было бы устраивать разборки на тему «А схерали это вы начали называть кулич кексом. «
А теперь о семечках кациуса.
Вот это гренки. Хлеб, поджаренный в масле. Можно готовить из ржаного хлеба, приправляя солью и чесноком. Можно делать из булки\белого хлеба. Обмакивая в сладкую смесь из яйца с молоком. Но это именно обжаренная в масле история.


А это крутон. Подсушенный в духовке или иным «сухим» способом продукт из специально выпеченного полуфабриката по структуре напоминающего чиабатту. Или из белого хлеба\багета и тд. Он просушен насквозь. По сути — это сухарик. Нежный, воздушный. Не солёный и не сладкий.
Его добавляют в блюда (салат цезарь, супы пюре, бульоны). Или едят в прикуску.

Вот это оладьи. Их готовят из дрожжевого теста (классический рецепт). И обжаривают на большом количестве масла. Они пышные и влажные.

А вот это панкейки. Их готовят из бездрожжевого теста. Пышность им придают взбитые белки. Выпекают на минимуме масла. Они эластичные, плотные и более сухие.

А вот это блины. И я хз, почему на уроках английского языка нам говорили, что по английски «блин» это «панкейк». Англоязычному человеку будет понятнее слово «креп» (блюдо французской кухни)

От наших блинов крепы не отличаются ничем, кроме традиции сервировки. Их редко едят просто так, макая в сметану или сгущенку. Креп, это блюдо. Если увидите в меню слово креп, значит вам подадут что то типа вот этого.

Вот это ватрушка. Сдобное дрожжевое тесто. Немного творога, смешанного с сахаром и яйцом.

А вот это чизкейк. Тоже «тесто с творогом». Но, согласитесь, есть нюанс.


Бедняга
Работаю в школе. И как же меня заебал школьный чат учителей и администрации! Он постоянно живёт и там постоянно что-то пишут! Я отключила уведомления и звуки, но он, блять, наполняется постоянно. И ладно, в будние дни, так ещё в выходные! Мало того, мне и ещё некоторым постоянно прилетает за то, что я не изволю отвечать в выходные/праздники/вечером. В этот чат присылают замены заболевших учителей. Вот как я должна приехать в школу к 8, когда сообщение о замене прислали в 11 вечера, когда я уже спала! Спала спокойным сном, зная, что мне завтра к пятому уроку, я могу спать до 10 утра. Но нет, в 8 меня будит звонок и истошный крик завуча: «Вы где, ваш класс разносит кабинет!» В пизде я! Или я уехала в воскресенье гулять по лесам, естественно, там не ловит, я вообще отключила интернет. Подъезжаю к городу, телефон разрывается: «Вы почему не отвечаете?» Говорю: «У меня выходной, я отдыхаю, а не сижу с телефоном в руках». В ответ: «Не надо хамить! У вас есть обязанности рабочие!» У меня есть выходной, блять! И я хочу отдыхать! Особый вид говняных сообщений — это сообщения на перемене. У меня 10 минут, чтобы закончить урок, вымыть доску, закрыть окна и кабинет, отнести ключ на вахту, взять ключ от другого кабинета в другом крыле школы, дотащить туда свою жопу и стопку тетрадей, а по пути не грех было бы поссать и сменить тампон, который уже давит изнутри. Вы действительно думаете, что у меня есть силы, время и желание смотреть в телефон, надеясь, что мне что-то написали? Да я физически не успею подойти к завучу за это время! Я даже поссать опять не успела! Интересно, есть где-нибудь ещё такие ебанутые чаты? Я уже устала бороться с ними. Я за прогресс, телефоны и интернет — удобно невероятно, но иногда хочется в эру дисковых телефонов, которые и то не у всех. А пока я задрипанная, заёбанная, потасканная и злая учительница русского языка и литературы, которая перед началом учебного года уже охуела от чатов, чатов, чатов!
Как получить m3u8 файл с сайта?
Так можно скачать видео через Streamlink
streamlink —http-header Origin=https://название_сайта «hls://https://какой-то_cdn.com/большой_путь_к_файл. » best -o свое_название.ts,
где в —http-header Origin=https://название_сайта указывает тот сайт, что указан в поле origin в браузере. При этом полностью удаляются расширения и остается только название видео (VIDEOID).
Но через Streamlink файл скачивается какой-то кривой. Весит гораздо меньше, все видео в артефактах, звук заикается.
Есть другой сайт, который тоже возвращает файл название_файла.m3u8. Там записано что-то
В одном из фрагментов, которые видны во вкладке network и выглядит так название_видео0.ts, в поле Request URL записано это https://какой-то_сервер.cc/путь_к_файлу/название_в. .
Если я скопирую ссылку файла m3u8 и вставлю в VLC, то у меня запускается нормальное видео.
Если я скопирую строчки из m3u8, создам у себя на компе m3u8 файл, вставлю туда строчки, которые указал выше, но при этом добавлю тот же сайт, что и в Request URL и получу что-то
, то и этот m3u8 файл будет работать.
Но проблема в том, что такой же способ с добавление названия сервера и расширения .ts не срабатывает с первым сайтом.
Эти сайты отличаются тем, что у первого сайта не показывается расширение у плейлиста и фрагментов, а у второго они есть. Если я открою ссылку на плейлист из первого сайта, то я получаю 403 ошибку, а у второго скачиваю m3u8 файл.
Плюс первый сайт возвращает ошибку 403, если я обращаюсь к нему через curl —verbose https://название_сайта/путь_к_файлу/файл, но если я сделаю такой же запрос, но с curl -H «Origin: https://сайт_из_поля_origin», то я получаю, то же самое, что и в спойлер 1.
Как из всего этого можно получить нормальный, рабочий m3u8 файл с первого сайта? Streamlink же как-то частично получает видео.
Надеюсь, кто-нибудь дочитал до конца.
- Вопрос задан более года назад
- 989 просмотров
Средний 1 комментарий
- Вконтакте
Попробуй сконвертировать m3u8 файл в готовый видеофайл с помощью ffmpeg (он умеет загружать), чтобы не перекодировало указывай кодек -c copy
Если сайт смотрит на http заголовки, который отправляет плеер/качальщик, и блокирует их, то очевидно их придется вручную подставлять, копируя из девконсоли браузера, один раз скопируй команду загрузки куска видео затем напиши скрипт, загружающий этой командой все куски локально и собирай с помощью ffmpeg
- Вконтакте
это значит сайт защищается от копирования, проверяя заголовки запроса (куки например), в браузере их устанавливает javascript а ffmpeg и твой curl по умолчанию нет, делай как я в ответе написал
ты не сможешь в m3u8 файл вставить желаемое (можно свой сервер поднять который будет запросы дополнять нужными origin, тогда ссылки в этом файле уже будут не на оригинальные а на твой сайт, но мне кажется тебе просто видео нужно скачать да?)
rPman, знать бы еще, куда и что подставлять. Я не разбираюсь во всем этом. Да, мне надо просто скачать видео. Сейчас для примера взял ссылку на m3u8 файл со второго сайта, вставил в ffmpeg как в первый раз и все без проблем получилось.
А в ffmpeg я могу передать параметр типа —http-header Origin=название_сайта_из_origin как в streamlink, но только для ffmpeg, чтобы запрос тоже как бы шел от название_сайта_из_origin.
как и во всем, либо ты разбираешься сам, либо ищешь кто за тебя будет все делать.
я вроде описал достаточно простой способ, даже особо программировать не надо
тебе надо из m3u8 файла сделать список ссылок на куски, делай как можешь, хоть в экселе, хоть вручную, хоть програмку из трех строчек напиши
затем копируй вручную из браузера из дев-консоли команду curl, и подставь ее вызов к каждой ссылке, подменяя ссылку этой скопированной команды на в каждой строчке свою, и получишь bat файл для загрузки кусков видео, затем подсовываешь m3u8 (чтобы ссылок не было только имена файлов) ffmpeg-у чтобы все файлы в текущем каталоге были, и получаешь собранный файл (вообще этот m3u8 на этом этапе сможет проиграть vlc)



что то сломалось под windows (ссылка генерируется рабочей для linux), где то ковычки не поставились, либо замени все двойные ковычки на одинарные, и возьми в двойные ковычки саму ссылку
теперь смотри, у тебя есть ссылка на скачивание m3u8 — пусть она будет https://example.com/test.m3u8
у тебя есть сам m3u8, тебе нужно из него вытащить (руками например) все его куски, вот эти 145xxx2.mp666/frag-1-v1-a1
ты в ссылке этой сгенерированной curl должен заменить test.meu8 на этот кусок, т.е. получишь https://example.com/145xxx2.mp666/frag-1-v1-a1
в конец строки curl добавь -o имя файла, куда будет сохранен кусок (иначе он выводится на экран) пусть к примеру это будет просто число 1,2,3,4. по номеру строки
у тебя там 8 ссылок вот 8 команд curl у тебя должно получиться (сохраняй в текстовый файл, назови его x.bat, по запуску он запустит по очереди все эти curl которые загрузят твои файлы)
после этого подправь m3u8 чтобы в нем были не пути на сайт а пути на файлы которые скачались, т.е. цифры 1,2,3. и все, готов файл для локального просмотра
p.s. порядок параметров curl может быть любой, обычно сначала ставят все заголовки и параметры запроса, а в конце ссылку и -o куда сохранить, если не умеешь программировать, рекомендую используя excel в первой колонке тупо скопировать curl команду без ссылки и -o, во вторую колонку добавить список ссылок, в третью список -o, в четвертую числа 1,2,3.
копируешь через буфер получившуюся таблицу, вставляешь в текстовый файл, получаешь объединенные строки (там между колонками будет табуляция, для bat это то же что и пробел, т.е. как обычный разделитель)
scopingVoices: Learn how to download live and replay .m3u8 URLs from Periscope with Go, the Twitter API and FFmpeg
![]()
One night I was hanging with a friend, and we wanted to start a new artistic project that used our skills as software developers and our love for sampling. After some brainstorming for a little, we decided we wanted to use a live-streaming app as source material for the new project. After researching several apps on the market, we decided on Periscope because of its real-time Q&A interaction, potential for broadcasting feedback loops and length of content. The main goal was to create a program that extracts audiovisual content from Periscope using FFmpeg.
Within minutes we found out there was no publically available API for Periscope which was a bummer. Then we searched Github and found a few projects that provided clues about how to access Periscope’s API through the Twitter API. After trying to get several projects up and running, but none of them did exactly what we wanted. We found a post from 2015 that explained what we wanted to do, but the workflow in the article did not work at the time we started the project. It didn’t matter though; we had all the pieces to do our own investigation.
We concluded that, with the help of the article and based on our own research is that:
- Get the broadcast_id from a Periscope URL and apply it to a Periscope API URL to create a valid GET request.
- The responding JSON from the GET request provides both live and replay video content in the form of .m3u8 files.
Once we had access to the .m3u8 URLS we intended to create an audiovisual processing utility for live-performance. For this, we would still use FFmpeg, but would start by getting the video content, strip & process the audio and then render the processed video. The workflow worked well as a prototype, but we transitioned our thinking into using the live stream and process the audio ourselves using a DAW during a performance. Broadcasting a .m3u8 URL in VLC was easy, and this workflow was successful. Next, we wanted to figure out how to process the video in real-time. For this we would need to get the video from VLC to the program Syphon which would allow us to route the stream to a video processing application built by Signal Culture. To our surprise, someone on Github created a branch of VLC with Syphon compiled with the application called VLCSyphon. We created content examples, and after about a month we liked our workflow. Then, out of nowhere, VLC and VLCSyphon didn’t like .m3u8 URLs and would crash after 3 seconds of playback. There seemed to be something wrong with how the chunked content was being pieced together and after several sessions of disappointment we settled on transitioning the idea to an audio only utility for the time being.
The first version was in Python and later I rebuilt it in Go to use concurrency. After adding concurrency, I attached an automation script that exports a Csound score and renders an audio file that combines all the sourced audio streams in a single track. The automation script mapped the download files to samplers in Csound, each being panned at different intervals in the stereo field while augmenting the pitch/speed of the sample using granular synthesis.
After learning more about Go in the past year, I’ve revisited the idea, refactor it, and I wanted to share the process with other humans. The post walks through creating a valid Periscope URL, format the URL for a GET request, and how to download content provided in the JSON response using FFmpeg.
Projects like this is how I fell in love with Computer Music research. The ability to blend art and programming is an art, and the Internet is the biggest sensor in the world. For all the curious humans, the project is on Github.
Legend
- Twitter Setup
- Creating the program
- Is it live or a replay?
- Constructing the core
- Removing duplicates, let’s rip!
- Try it out
Requirements
Twitter Setup
The project requires a Twitter Developer account and Twitter Access Tokens. The Anaconda library uses the credentials to access Twitter API endpoints in Go. To learn how to set environmental variables for Go, check out my post on Dev.to.
Creating the program
Start by creating a fresh Go program named scopingVoices.js file. Installing the libraries below is not necessary because when we build the project using go build all the dependencies will be installed thanks to Go modules.
Before getting into it, let’s create two structs. The first struct is for the Twitter credentials named TwitterCreds.
And the second struct is for receiving URLs from the Periscope API named Periscope.
Is it live or a replay?
Before moving to the main function, create a function named acquireStreamURLs that ingests Periscope API URLs and creates a GET request for each URL. The JSON response of each GET request is parsed using a switch to determine if the URL is a replay or a live-stream.
Below is a standard GET request. The resp.Body reads the body until EOF using ioutil.ReadAll. Then Unmarshal the JSON data and store the resulting body in the record variable. We can now access the Periscope API JSON response can now via the record variable.
Next, use a switch to check if the record.ReplayURL within the Periscope API contains a “?type=replay” as a substring.
If true (the record.ReplayURL contains the substring “?type=replay”), check if the string contains any data. And if the key contains a URL trim the substring of the replayURL and pass it to the outputURL variable.
If false, (the record.ReplayURL does not contain the substring “?type=replay”), check if record.LhlURL contains any data. And is key contains a URL, pass it to the outputURL variable.
Constructing the core
Add your Twitter credentials to the TwitterCreds struct using os.Getenv. The function will pull the Twitter credentials from the
/.bash_profile and will make them available within the program.
Use anaconda to set the ConsumerKey and the ConsumerSecret.
Create a NewTwitterApi connection. It will return a struct for accessing various Twitter endpoints.
Search Twitter for the keyword “periscope” and seek 250 results by setting the count parameter.
Start by creating a string array variable named collectedURLs to collect all of the valid .m3u8 Periscope URLs from the GET request in the acquireStreamURLs function. The function created in the previous section is applied in this section in a few moments.
Iterate over searchResult.Statuses using range to pick out individual users statuses. Within the loop, use range again to iterate over the status.Entities.Urls from Twitter’s Entites object.
Within the second loop, access relevant video content via the entities.Expanded_url key. The URLs are used to construct a new Periscope API call, but not all of them are from Periscope. Since there is no way to predict the type of URL returned, use a switch with a conditional that checks the Expanded_url for the substring “https://www.pscp.tv/w/“.
If true (the entities.Expanded_url contains the substring “https://www.pscp.tv/w/"), split the string in two at the delimiter “https://www.pscp.tv/w/". The second part of the split string is a broadcast_id and combing it with the Periscope URL will create a new Periscope API URL.
Some URLs found within the true statement are suitable for a GET request, but some of them contain a time parameter that looks like “?t”. The parameter will cause the GET request to fail, so use a switch to check the apiURL for the substring “?t”.
If true (the apiURL contains the substring “?t”), split the string at the delimiter and trim the end to make it a URL suitable for a GET request within the requestURLs variable. In return, pass the URL to the acquireStreamURLs function created earlier in the tutorial to create a GET request. The variable getStreamURL returns valid .m3u8 URLs links from the JSON response and aggregated with the collectedURLs variable.
If false (the apiURL does not contain the substring “?t”), pass the apiURL to the function to create a GET request. The returned .m3u8 URLs pass to the collectedURLs variable.
Now we have collected all the available .m3u8 URLs from Periscope. Fantastic!
Removing duplicates, then let it rip!
Before moving forward to FFmpeg, it is important to check for duplicates URLs. Iterate over collectURLs, map the URLs to encounteredFiles and append the pruned array to nodupsCollectedURLs.
When the program runs an argument is required. The incoming argument is used to pass an output path for files downloaded using FFmpeg. Use dir to access the command-line argument at the start of the program.
Get the current time of the programs execution and format it the time to year-month-day-hours-minutes-seconds. It will be used as timestamp for exported wav files.
Iterate over the clean directory of .m3u8 Periscope URLs.
Inside of the loop, create a new .wav filename for each URL using formattedTime variable and the current index of the current file.
Create a new exec.Command that executes FFmpeg with the following arguments, noting the addition of previous variables to determine the input and the output file. Then run the command.
Try it out
Build the program.
Run the program.
Conclusion
It’s important to realize that programming is an art and we often we disregard software/hardware as processes to help us externally when in reality we are examining and even auditing ourselves. We build programs to mimic granular processes and this usually makes us follow similar paths. This project represents the tangible reality of accessing memories in a vast ocean of the mind, we are the humans trying to recollect and the internet is the ocean of experience we put out there. Think out of the box, connect things that “shouldn’t” or “can’t” connect and don’t stop being curious.