Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.85/13: Рейтинг темы: голосов - 13, средняя оценка - 4.85
101 / 38 / 0
Регистрация: 16.09.2014
Сообщений: 426

Скриншоттер ютуб-роликов

27.08.2020, 19:56. Показов 2496. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет всем!
Приходится часто и много снимать скриншоты с ютуб-роликов, представляющих собой не собственно видео съёмку, а просто набор картинок, сменяющих друг друга, типа таких:
https://www.youtube.com/watch?v=4xgmAUeAldg
https://www.youtube.com/watch?v=wy-qLaE0g4Q

Переходы между картинками реализуются самыми разными эффектами и в этот промежуток пиксели находятся в динамическом изменении, после чего очередная картинка полностью выводится и 2-5 секунд остаётся без изменения, то есть пиксели на экране не изменяются. Задача стоит в создании скриншоттера, который автоматически будет определять, что картинка новая, и делать её скриншот. Проблема не в собственно коде - определять цвет заранее определённых пикселей (десятка в разных местах экрана будет достаточно, я думаю) и делать скриншоты и сохранение в определённую папку я умею, но не совсем понятен алгоритм действий. Буду благодарен за подсказки в виде:
1 Определить цвета пикселей
2 Через полсекунды определить ещё раз
3 если есть изменения сделать то-то
4 если нет сделать то-то
И так далее и тому подобное
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.08.2020, 19:56
Ответы с готовыми решениями:

скриншоттер на С
ПЛИЗ!!!!!!!....помогите найти прогу(текст проги), которая сохраняет копию экрана в bmp формат, язык программирования - С под DOS

Монтаж роликов
Добрый день хочу попробовать монтаж видио роликов, на Movavi Video Suite, не очень понравилось, есть что не буть на чём можно действительно...

Раскрутка роликов на YouTube
SMM-PARTNER предлагает Вам свои услуги по раскрутке роликов на YouTube 1. Реальные просмотры 2. Комментарии к видеороликам 3....

15
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
27.08.2020, 22:54
Лучший ответ Сообщение было отмечено Catstail как решение

Решение

Получить пиксели можно через GetPixel (если пикселей мало), либо GetDiBits если пикселей много. Сравниваешь кадры и если разница больше порогового значения - устанавливаешь флаг, который следит пока изображения не перестанут изменяться. Как только изображения перестали изменяться - убираешь флаг, сохраняешь скриншот. Т.к. при использовании GetDiBits пиксели уже есть, то их очень просто сохранить в BMP, либо заюзав GDI+ или WIC сохранить в PNG/JPG/и т.д.
Я бы конечно если бы реазиовывал подобную задачу и мне данный инструмент был бы нужен в повседневной работе, я бы анализировал не скриншоты, а напрямую видеопоток. Так и скорость была бы выше и не приходилось бы обеспечивать видимость региона.
1
7 / 7 / 0
Регистрация: 10.07.2015
Сообщений: 69
30.08.2020, 04:15
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
Attribute VB_Name = "ModImageCompare"
Option Explicit
 
Private Type BITMAPINFOHEADER
        biSize As Long
        biWidth As Long
        biHeight As Long
        biPlanes As Integer
        biBitCount As Integer
        biCompression As Long
        biSizeImage As Long
        biXPelsPerMeter As Long
        biYPelsPerMeter As Long
        biClrUsed As Long
        biClrImportant As Long
End Type
 
Private Type RGBQUAD
        rgbBlue As Byte
        rgbGreen As Byte
        rgbRed As Byte
        rgbReserved As Byte
End Type
 
Private Type BITMAPINFO
        bmiHeader As BITMAPINFOHEADER
        bmiColors As RGBQUAD
End Type
 
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFOHEADER, ByVal wUsage As Long) As Long
 
Private lonPix_1() As Long
Private lonPix_2() As Long
 
Public Function ImagesSame(Pic_1 As PictureBox, Pic_2 As PictureBox) As Boolean
    Dim bih_1 As BITMAPINFOHEADER, bih_2 As BITMAPINFOHEADER
        
    With bih_1
        .biSize = Len(bih_1)
        .biPlanes = 1
        .biWidth = Pic_1.ScaleWidth
        .biHeight = Pic_1.ScaleHeight
        .biBitCount = 32
    End With
    
    bih_2 = bih_1
    
    ReDim lonPix_1((bih_1.biWidth * bih_1.biHeight) - 1)
    ReDim lonPix_2((bih_2.biWidth * bih_2.biHeight) - 1)
    
    GetDIBits Pic_1.hDC, Pic_1.Picture.Handle, 0&, bih_1.biHeight, lonPix_1(0), bih_1, 0
    GetDIBits Pic_2.hDC, Pic_2.Picture.Handle, 0&, bih_2.biHeight, lonPix_2(0), bih_2, 0
    
    ImagesSame = ComparePixels
    
    Erase lonPix_1()
    Erase lonPix_2()
End Function
 
'Returns true if pixels from both arrays are the same.
Private Function ComparePixels() As Boolean
    Dim lonU1 As Long, lonU2 As Long
    Dim bolFound As Boolean, lonLoop As Long
    
    lonU1 = UBound(lonPix_1())
    lonU2 = UBound(lonPix_2())
    
    If lonU1 = lonU2 Then
        For lonLoop = LBound(lonPix_1()) To lonU1
            If lonPix_1(lonLoop) <> lonPix_2(lonLoop) Then
                bolFound = True
                Exit For
            End If
        Next lonLoop
        
        ComparePixels = Not bolFound
    Else
        ComparePixels = False
    End If
    
End Function
Video screenshots can only be taken at the front desk
0
101 / 38 / 0
Регистрация: 16.09.2014
Сообщений: 426
03.09.2020, 06:26  [ТС]
xxdoc большое спасибо за профессиональный код! Обязательно использую!

Но моя проблема не решается, как мне ни стыдно признаться, я уже 2-3день не могу сообразить алгоритм действий То есть фактически есть:

Подпрограммы:
Visual Basic
1
2
3
Private Sub Timer1_Timer()
Private Sub GetPixelsColor()
Private Sub ComparePixels() возвращает FlagIsSame  (True\False)
Флаги (Boolean):
Visual Basic
1
2
FlagIsSame  
FlagIsScreened(может это лишнее?)
2 массива:
Visual Basic
1
2
Dim PixelsPrev(0 To 9) As Long ' цвета пикселей при предыдущем считывании
Dim PixelsLast(0 To 9) As Long ' цвета пикселей при последнем считывании
и вот как организовать логику действий я не могу сообразить То есть я прошу у вас даже не столько код (xотя ещё раз огромное спасибо за интереснейший код!) сколько просто словесное описание логики последовательности действий:

1 Снять пиксели
2 Сравнить
3 Если FlagIsSame = True то...

и так далее

Вот я вымучил прогу вся "обвеска" работает но сам процесс не могу сообразить
Может кто посмотрит и укажет что надо сделать, там совсем капелюшка кода, в самом низу нужный блок кода выделен такими строками:
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Вложения
Тип файла: zip YouTube Screenshotter.zip (95.2 Кб, 6 просмотров)
0
sleep
 Аватар для I can
4926 / 4576 / 840
Регистрация: 13.04.2015
Сообщений: 9,727
03.09.2020, 06:42
giaber, а если пересмотреть подход? Не делать скриншоты, а скачать видео и нарезать его на ключевые кадры?
0
101 / 38 / 0
Регистрация: 16.09.2014
Сообщений: 426
03.09.2020, 08:39  [ТС]
Долго и муторно! Когда именно видео так и делаю прогой Free Video Editor, но когда ролик типа такого: "Cтопицот Лучшиx дизайнов беседки" состоит из стопицот миллионов картинок которые надо соxранить каждую отдельно, чтоб потом разбить по папкам по стилям "ренессанс", "ампир" и "барокко" и такиx роликов десятка 2-3, то это, сами понимаете, тот ещё гемор!
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
03.09.2020, 15:07
Цитата Сообщение от giaber Посмотреть сообщение
Долго и муторно! Когда именно видео так и делаю прогой Free Video Editor, но когда ролик типа такого: "Cтопицот Лучшиx дизайнов беседки" состоит из стопицот миллионов картинок которые надо соxранить каждую отдельно, чтоб потом разбить по папкам по стилям "ренессанс", "ампир" и "барокко" и такиx роликов десятка 2-3, то это, сами понимаете, тот ещё гемор!
Нет. Он имеет в ввиду программно. Я тоже об этом говорил - нужно анализировать видеопоток напрямую. Это и правильней, т.к. не мешает работать пользователю и более эффективно, т.к. просматривать поток можно гораздо быстрее чем идет видео.
Я бы помог в решении подобной задачи если ты используешь этот путь.
1
101 / 38 / 0
Регистрация: 16.09.2014
Сообщений: 426
03.09.2020, 19:36  [ТС]
I can, The trick! Это ж для меня космический уровень! Я ж VB на уровне годовалого младенца знаю!

Добавлено через 6 минут
I can, The trick!.
Спасибо большое, конечно, за такой оптимизм относительно моиx умственныx способностей, но давайте лучше по старинке, по рабоче-крестьянски так сказать:For Next, If Then - всё такое родное, простое, сермяжное...
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
03.09.2020, 19:53
giaber, ничего сложного. Используя Media Foundation можно прямо по URL иметь доступ к видео и кадрам.
Приблизительный алгоритм:
  1. Получаешь URL к видеопотоку (к примеру через get_video_info, либо через youtube-dl);
  2. Создаешь Source Resolver (IMFSourceResolver) через MFCreateSourceResolver;
  3. Создаешь Media Source (IMFMediaSource), передавая URL до потока в CreateObjectFromURL;
  4. Создаешь Media Reader (IMFSourceReader) используя MFCreateSourceReaderFromMediaSource, не забыв включить процессинг видео (MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING);
  5. Далее извлекаешь видео-дорожку IMFSourceReader::GetCurrentMediaType и получаешь размер кадра через MFGetAttributeSize (MF_MT_FRAME_SIZE);
  6. Затем задаешь формат пикселей изображения и другие атрибуты как интерлейсинг, аспект через SetGUID/SetUINT32 и т.д;
  7. Читаешь кадр через IMFSourceReader::ReadSample пока не получишь флаг MF_SOURCE_READERF_ENDOFSTREAM;
  8. Конвертируешь в единый буфер через IMFSample::ConvertToContiguousBuffer, фиксируешь в памяти пиксели через IMFMediaBuffer::Lock;
  9. Проверяешь через разницу на порог (т.к. сжатие с потерями то необходимо вводить порог, т.е. контрольная сумма не пойдет) пиксели, принимая решение о том стоит ли сохранять изображение или нет;
  10. Если изображение нужно сохранить, то инициализируешь новый битмап через GdipCreateBitmapFromScan0 и сохраняешь его через GdipSaveImageToFile.
0
101 / 38 / 0
Регистрация: 16.09.2014
Сообщений: 426
03.09.2020, 21:05  [ТС]
The trick огромное спасибо за пошаговое руководство! Взглянул одним глазком на те ссылки что вы написали и в дикой панике рука потянулась к кнопке RESET! до сиx пор пульс 120! Когда нибудь я с удовольствием попытаюсь во всём этом разобраться тема интереснейшая! Но вы даже не представляете с вашего уровня профессионализма сколько времени это у меня займёт ! И вообще осилю ли! Поэтому сейчас я всё же xочу добить эту мою, с позволения сказать, программу обычными ламерскими методами, тем более что та проблема о которой я спрашиваю всё равно встаёт и при рекомендуемом вами методе насколько я понимаю
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
06.09.2020, 17:55
Лучший ответ Сообщение было отмечено giaber как решение

Решение

Цитата Сообщение от The trick Посмотреть сообщение
giaber, ничего сложного. Используя Media Foundation можно прямо по URL иметь доступ к видео и кадрам.
Приблизительный алгоритм:
  1. Получаешь URL к видеопотоку (к примеру через get_video_info, либо через youtube-dl);
  2. Создаешь Source Resolver (IMFSourceResolver) через MFCreateSourceResolver;
  3. Создаешь Media Source (IMFMediaSource), передавая URL до потока в CreateObjectFromURL;
  4. Создаешь Media Reader (IMFSourceReader) используя MFCreateSourceReaderFromMediaSource, не забыв включить процессинг видео (MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING);
  5. Далее извлекаешь видео-дорожку IMFSourceReader::GetCurrentMediaType и получаешь размер кадра через MFGetAttributeSize (MF_MT_FRAME_SIZE);
  6. Затем задаешь формат пикселей изображения и другие атрибуты как интерлейсинг, аспект через SetGUID/SetUINT32 и т.д;
  7. Читаешь кадр через IMFSourceReader::ReadSample пока не получишь флаг MF_SOURCE_READERF_ENDOFSTREAM;
  8. Конвертируешь в единый буфер через IMFSample::ConvertToContiguousBuffer, фиксируешь в памяти пиксели через IMFMediaBuffer::Lock;
  9. Проверяешь через разницу на порог (т.к. сжатие с потерями то необходимо вводить порог, т.е. контрольная сумма не пойдет) пиксели, принимая решение о том стоит ли сохранять изображение или нет;
  10. Если изображение нужно сохранить, то инициализируешь новый битмап через GdipCreateBitmapFromScan0 и сохраняешь его через GdipSaveImageToFile.
В общем сделал небольшую утилиту основанную на данном алгоритме. Самое сложное было реализовать получение URL к видео из ссылки на Youtube.

Для получения ссылок на видеопотоки разработан класс CYoutubeVideoProvider. Данный класс на основе запросов к серверу получает информацию о видеопотоках (размеры, тип, прямую ссылку) из которой можно уже извлечь непосредственно кадры. Т.к. приложение в любом случае требует подключение к интернету то реализовывать JSON парсер я не стал. Для парсинга используется JS код который скачивается с гитхаба и запускается в ScriptControl'е. Т.к. алгоритм обфускации довольно муторный у ютуба (и постоянно меняются), то возможно что некоторые ссылки не будут работать.

Для обработки видео используется Media Foundation для которого я специально написал библиотеку типов и модуль. Всю логику инкапсулирует класс CVideoAnalyser. Он уже непосредственно анализирует пиксели и кидает событие NewSlide если алгоритм задетектировал новый слайд.


Вложения
Тип файла: zip YoutubeCapture.zip (189.7 Кб, 28 просмотров)
2
101 / 38 / 0
Регистрация: 16.09.2014
Сообщений: 426
07.09.2020, 14:12  [ТС]
Das Ist Fantastisch !!! Работает как атомные часы!
Спасибо!!! Спасибо!!! Спасибо!!! (стоя на коленяx отбивает поклоны, то выпрямляясь, воздевая руки то стукаясь лбом о землю)
0
7 / 7 / 0
Регистрация: 10.07.2015
Сообщений: 69
24.09.2020, 14:21
@the trick

Is there a demo for your method. Want to see

Добавлено через 13 минут
Для обработки видео используется Media Foundation для которого я специально написал библиотеку типов и модуль. Всю логику инкапсулирует класс CVideoAnalyser. Он уже непосредственно анализирует пиксели и кидает событие NewSlide если алгоритм задетектировал новый слайд.


@the trick

Is there a demo for your method. Want to see
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
24.09.2020, 22:29
xxdoc, see the attachment.
0
7 / 7 / 0
Регистрация: 10.07.2015
Сообщений: 69
25.09.2020, 05:48
It doesn't seem to be this code when I downloaded it yesterday. You updated it. Thank you.
0
7 / 7 / 0
Регистрация: 10.07.2015
Сообщений: 69
27.09.2020, 06:23
It's really great, but the speed is very slow, and ask if it supports other streaming videos
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.09.2020, 06:23
Помогаю со студенческими работами здесь

Подмена названий у роликов
В папке на сервере лежат 10 роликов: domain.com/public_html/videos/01.mp4 domain.com/public_html/videos/02.mp4 .. ...

Создания флеш роликов
пож, дайте ссылку на видеоурок по созданию флеш-меню в Macromedia Flash 8 ! поиском найти не могу, тока написанные уроки, т.к. не знаю...

Насчёт заработка на переводе роликов
Всем привет. Имеются отличные знания в области английского языка, т.е. свободное владение и нахождение в течение некоторого времени на...

Повторение роликов в Burnout Paradise
в начале игры какаято баба начинает объяснять где ездить и т.д Когда закончила начитает снова!! Это глюк или что??

Запись роликов с экрана монитора
Здравствуйте! Предложите, пожалуйста, программу для записи роликов *.avi до 100 Mb, с экрана монитора. Кто чем пользуется? Предлагайте,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main(). . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru