Перейти к содержанию

Голосования

Голосования — это витрина опроса Twitch на сцене OBS плюс пульт в кабинете. Сам опрос живёт в Twitch: PulseCaster его не подменяет, а показывает и вызывает те же действия, что и панель опросов на самом Twitch.

Опрос, запущенный из панели Twitch, со Stream Deck или чужим ботом, появится на сцене так же, как запущенный из кабинета. Никакого отдельного «нашего» голосования нет — есть один опрос канала.

Не путать с командой !опрос

Команда !опрос в чате считает сообщения «да» и «нет» и к этому разделу отношения не имеет. Здесь — настоящий опрос Twitch: с кнопками у зрителей, голосом за баллы канала и итогами в чате.

Раздел устроен так же, как Предикты: если вы уже настроили предикт на сцене, здесь всё будет знакомо. Отличие в том, что у опроса нет ставок и победителя не выбирают руками — побеждает вариант с большинством голосов.

Нужна помощь разработчика?

Напишите mrgorkiy в Telegram. Укажите страницу, ожидаемый результат, что произошло и шаги для повторения. Можно приложить скриншот или короткое видео. Перед отправкой закройте токены, коды подтверждения и приватные ссылки OBS.

Что нужно, чтобы это работало

Условие Зачем Что будет без него
Статус Affiliate или Partner Twitch разрешает опросы только им Запуск вернёт отказ Twitch
Подключён Twitch-аккаунт владельца Через него идут все вызовы Раздел скажет, что аккаунт не подключён
Право channel:read:polls Голоса зрителей приходят событиями EventSub Проценты на сцене замрут между действиями
Право channel:manage:polls Пульт запускает и завершает опрос Пульт покажет опрос, но кнопки будут недоступны

Права выдаются при подключении Twitch-аккаунта владельца. Если раздел просит переподключиться — значит, токен выпущен до появления этих прав.

Кому в команде открыт раздел

Владельцу канала — всегда. Модератору — только если вы выдали ему зону Голосования в разделе Модераторы. Она отдельная от зоны Предикты: запуск опроса ничего у зрителей не забирает, а итог предикта раздаёт баллы и не отменяется, поэтому эти права удобно выдавать порознь.

Что можно делать

На странице Владелец → Голосования две вкладки.

Голосования — всё, что нужно во время эфира:

  • пульт: идущее голосование с отсчётом и голосами, Завершить и показать итоги, Убрать без итогов;
  • итог последнего голосования: победитель, ничья или «никто не проголосовал»;
  • заготовки с запуском в одну кнопку и форма для новой заготовки.

Сцена OBS — то, что настраивается один раз:

  • сколько итоги висят на сцене и показывать ли число голосов;
  • оформление сцены с превью: цвета, размер текста, скругление, положение в источнике и появление;
  • приватная OBS-ссылка для Browser Source и демонстрационный режим.

Как голосование ведёт себя на сцене

Стадия Что на сцене
Голосование идёт опрос виден, проценты растут, лидер подсвечен, идёт обратный отсчёт
Время вышло итоги видны ещё 15 секунд, победитель подсвечен
Завершено досрочно итоги видны так же, ещё 15 секунд
Ничья подсвечены все варианты, поделившие первое место
Никто не проголосовал опрос виден с подписью «Никто не проголосовал»
Убрано без итогов источник пустеет сразу
Удалено модерацией Twitch источник пустеет сразу
Голосования нет источник пустой

15 секунд — значение по умолчанию, оно настраивается во вкладке Сцена OBS. Диапазон — от 0 до 3600 секунд; 0 означает «убрать сразу».

Пока голосование идёт, оно видно всегда — это не настраивается: иначе зритель не поймёт, за что голосует.

Twitch через некоторое время сам убирает итоги из чата. На сцене это показ не сокращает: итоги висят столько, сколько задано в кабинете.

Обратный отсчёт страница ведёт сама. Сервер присылает момент конца голосования, а не остаток, поэтому цифры идут ровно даже при коротком обрыве связи.

Два способа закончить раньше

Кнопка Что делает Twitch Что на сцене
Завершить и показать итоги останавливает голосование и объявляет итог в чате итоги с победителем, как после конца времени
Убрать без итогов останавливает голосование и убирает его из чата без результата источник пустеет сразу

Убрать без итогов подходит, если голосование запустили по ошибке. Кабинет попросит подтвердить это действие: вернуть опрос после снятия нельзя.

Заготовки

Заготовка — это заранее собранное голосование: вопрос, варианты, длительность и цена дополнительного голоса. Запуск делается одной кнопкой, без набора текста в эфире.

Длительность вводится с переключателем секунды / минуты: 2 минуты и 120 секунд — одно и то же, но в списке заготовок это видно без пересчёта в уме.

Дополнительные голоса за баллы канала

Первый голос у каждого зрителя бесплатный. Если включить опцию, зрители смогут докупать голоса за баллы канала — столько, сколько захотят. Цена одного голоса задаётся в заготовке.

Потраченные баллы не возвращаются ни при каком итоге: это не ставка, а покупка голоса. Такие голоса Twitch учитывает в процентах наравне с бесплатными; в пульте видно, сколько голосов куплено.

Заготовки живут в PulseCaster, а не в Twitch. Удаление заготовки не влияет на идущее голосование.

Ограничения Twitch

Кабинет проверяет поля теми же мерками, что и Twitch, поэтому отказ приходит до запуска, а не после.

Поле Ограничение
Вопрос до 60 символов
Варианты от 2 до 5, каждый до 25 символов
Длительность от 15 секунд до 30 минут
Цена дополнительного голоса от 1 до 1 000 000 баллов
Одновременных голосований ровно одно на канал

Голосования за Bits Twitch больше не поддерживает, поэтому в кабинете их нет.

Оформление сцены

Во вкладке Сцена OBS блок Оформление на сцене меняет вид голосования без CSS. Слева превью, справа настройки: нажмите на элемент превью — откроются его настройки. Кнопки Голосование и Итог переключают пример, Повторить проигрывает появление ещё раз.

Настройка Что меняет
Положение в источнике Сверху или Снизу прижимает плашку к краю источника OBS. Как в адресе ссылки оставляет решение параметру position в адресе, без него — сверху
Появление откуда плашка выезжает: снизу, сверху, слева, справа или просто проявляется
Панель цвет фона, его непрозрачность и скругление углов
Текст основной цвет (вопрос, названия вариантов, проценты), второстепенный (таймер, подписи, число голосов) и размер текста от 12 до 32 px; вопрос и таймер крупнее, подписи мельче — пропорции сохраняются
Варианты цвет полос вариантов и цвет лидера: пока голосование идёт, вариант с наибольшим числом голосов подсвечивается им
Победитель цвет полосы и значка победившего варианта и подписи с итогом

Нажмите Сохранить оформление: открытый источник в OBS подхватит изменения сам, перезагружать его и менять ссылку не нужно. Это работает и в демонстрационном режиме: выдуманное голосование продолжает крутиться, а цвета меняются сразу. Вернуть стандартное подставляет встроенную тему — она тоже применяется только после сохранения.

Пока оформление не сохраняли, голосование выглядит так же, как раньше. Правила из поля Custom CSS в OBS сильнее настроек кабинета, поэтому готовые варианты оформления ниже задают свои цвета поверх них. С ?style=none в адресе встроенная тема отключена, и из этих настроек действует только положение.

OBS-ссылка

Публичная ссылка имеет вид:

/{channel}/poll/{link_id}/{token}

Токен показывается только сразу после создания или замены. PulseCaster хранит только хэш токена, поэтому старую полную ссылку нельзя повторно раскрыть из настроек. Если URL потерялся, нажмите Заменить ссылку и вставьте новый адрес в OBS.

Если ссылка выключена, токен неверный или канал не совпадает, страница отдаёт 404.

Ссылка голосования и ссылка предикта — разные: на сцену добавляются два источника, каждый со своим адресом.

Как добавить в OBS

  1. Откройте Владелец → Голосования → вкладка Сцена OBS.
  2. Нажмите Создать ссылку и скопируйте адрес.
  3. В OBS добавьте источник Browser / Браузер.
  4. Вставьте ссылку в поле URL.
  5. Задайте ширину 620 и высоту 480. Этого хватает на пять вариантов с длинными названиями; если подключаете крупный шрифт, проверьте демонстрационный режим и при необходимости увеличьте высоту.
  6. При желании вставьте своё оформление в поле Custom CSS.

Кабинет обновляет состояние в фоне без замены страницы экраном загрузки и без сброса несохранённых настроек и начатой заготовки.

Страница прозрачная и приходит с готовым оформлением — той же тёмной панелью, что у предикта, поэтому оба источника на одной сцене выглядят одной семьёй. Страница обновляется через SSE — перезагружать источник при запуске и завершении не нужно.

Параметры адреса

Параметр Что делает
?demo=1 крутит выдуманное голосование: голоса прибывают, потом победитель, ничья, «никто не проголосовал»
?style=none отключает декоративную тему; для полностью собственного CSS, а не шаблонов ниже
?position=bottom прижимает голосование к нижнему краю источника, если в кабинете выбрано Как в адресе ссылки
?position=top прижимает к верхнему краю (так же ведёт себя адрес без параметра)

?demo=1 нужен, чтобы подбирать CSS: настоящее голосование для этого запускать не надо. Демонстрационное голосование живёт только на этой странице, в Twitch оно не попадает.

Уберите ?demo=1 перед эфиром

Пока параметр в адресе источника, страница показывает выдуманное голосование и не следит за настоящим.

Положение проще задать в блоке Оформление на сцене: выбор Сверху или Снизу там сильнее параметра в адресе и применяется к уже добавленному источнику без правки URL. Параметр position нужен, когда положение хранится в адресе конкретного источника — так копировались ссылки раньше. Параметры совмещаются через &: ?demo=1&position=bottom.

style=none нужен только для оформления с нуля. Готовые CSS ниже дополняют встроенную тему: удалите style=none из адреса, полностью замените содержимое поля Custom CSS выбранным блоком и обновите источник OBS. Не смешивайте несколько шаблонов. Без темы не будет отступов, цветов и полос; скрытие отсчёта после конца, значка у не победивших вариантов и отключённого числа голосов сохраняется.

Стили в OBS

Оформление по умолчанию целиком завёрнуто в :where(), у которого нулевой вес. Поэтому обычное правило из Custom CSS — например .pc-poll { ... } — сильнее любого правила темы, и !important не нужен.

Стабильная структура страницы:

<div class="pc-poll"
     data-status="active"
     data-visible="true"
     data-choices="3"
     data-votes="true"
     data-hurry="false"
     data-result=""
     data-poll-id="f3c1...">
  <div class="pc-poll-head">
    <span class="pc-poll-title">Во что играем после перерыва?</span>
    <span class="pc-poll-timer" data-seconds="95">01:35</span>
  </div>
  <span class="pc-poll-points">Дополнительный голос — 250 баллов</span>
  <span class="pc-poll-note"></span>
  <ol class="pc-poll-choices">
    <li class="pc-poll-choice"
        data-index="1"
        data-choice-id="a1b2"
        data-leader="true"
        data-winner="false"
        data-percent="54.0"
        style="--pc-poll-percent: 53.95;">
      <span class="pc-poll-choice-head">
        <span class="pc-poll-choice-title">Doom</span>
        <span class="pc-poll-choice-badge" hidden>Победитель</span>
      </span>
      <span class="pc-poll-choice-stats">
        <span class="pc-poll-choice-percent">54%</span>
        <span class="pc-poll-choice-votes">41 голос</span>
      </span>
      <span class="pc-poll-choice-bar"><span class="pc-poll-choice-fill"></span></span>
    </li>
  </ol>
  <span class="pc-poll-total">Всего 76 голосов</span>
</div>

Что можно использовать в CSS:

Селектор или атрибут Что это
.pc-poll корень: плашка, рамка, фон, размер
.pc-poll-title вопрос
.pc-poll-timer обратный отсчёт до конца голосования
.pc-poll-points подсказка про дополнительный голос за баллы, пока голосование идёт
.pc-poll-note подпись итога: победитель, ничья, «никто не проголосовал»
.pc-poll-choice один вариант целиком
.pc-poll-choice-title название варианта
.pc-poll-choice-badge значок «Победитель» или «Ничья»
.pc-poll-choice-percent доля голосов в процентах
.pc-poll-choice-votes число голосов с подписью: «41 голос», «23 голоса»
.pc-poll-choice-bar, .pc-poll-choice-fill полоса и её заполнение
.pc-poll-total итоговая строка под вариантами
[data-status="active\|completed\|terminated"] оформление под стадию
[data-result="winner\|tie\|no_votes"] итог после конца голосования
[data-choices] сколько всего вариантов
[data-leader="true"] вариант, который лидирует, пока голосование идёт
[data-winner="true"] победивший вариант; при ничьей — все поделившие первое место
[data-index] номер варианта по порядку, чтобы раскрасить варианты по-разному
[data-hurry="true"] последние десять секунд голосования
[data-votes="false"] число голосов выключено в кабинете
--pc-poll-percent доля голосов числом, для ширины полосы

Скрытием управляет сама страница: когда срок показа вышел, она ставит data-visible="false". Своё правило display для .pc-poll это не сломает. Если хочется своей анимации исчезновения, верните показ более сильным селектором и анимируйте прозрачность:

html body .pc-poll[data-visible] { display: flex; }
.pc-poll { transition: opacity 0.4s ease; }
.pc-poll[data-visible="false"] { opacity: 0; }

Готовые варианты оформления

Каждый вариант рассчитан на источник шириной около 620 пикселей. Вставляйте CSS в поле Custom CSS у Browser Source.

Во что играем? Doom54% Quake30% Half-Life16%
Список по умолчанию Тема из коробки: стеклянная плашка, фиолетовые полосы, лидер ярче.
54%Doom 30%Quake 16%Half-Life
Табло Крупные проценты в ряд, по цвету на вариант. Читается с другого конца комнаты.
Во что играем? Doom 54% Quake 30%
Без плашки Только текст и тонкие полосы поверх игры или камеры.

Список по умолчанию

Оформление по умолчанию уже такое — этот блок нужен, если хочется поменять цвета или размер, не собирая всё с нуля. Достаточно переопределить переменные:

.pc-poll {
  --pc-poll-accent: #38bdf8;
  --pc-poll-leader: #7dd3fc;
  --pc-poll-win: #a3e635;
  --pc-poll-surface: rgba(6, 10, 18, 0.9);
  --pc-poll-text: #ffffff;
  --pc-poll-muted: #9aa7bd;
  --pc-poll-radius: 26px;

  font-family: "Bahnschrift", "Segoe UI", system-ui, sans-serif;
}

.pc-poll-title {
  font-size: 26px;
  text-transform: uppercase;
}

.pc-poll-choice-bar {
  height: 14px;
}

Табло

Варианты стоят в ряд, у каждого — крупный процент и свой цвет по номеру. Число голосов и подсказка про баллы скрыты, чтобы табло читалось с первого взгляда. Рассчитано на два–четыре варианта: пятый встанет вторым рядом.

html,
body {
  margin: 0;
  background: transparent;
  overflow: hidden;
}

.pc-poll {
  gap: 12px;
  padding: 16px 20px;
  font-family: "Segoe UI", system-ui, sans-serif;
}

.pc-poll-head {
  justify-content: center;
  gap: 12px;
}

.pc-poll-title,
.pc-poll-note {
  text-align: center;
}

.pc-poll-title {
  font-size: 22px;
}

.pc-poll-choices {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.pc-poll-choice {
  flex: 1 1 130px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 12px 8px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.05);
}

/* Свой цвет каждому варианту по номеру. */
.pc-poll-choice[data-index="1"] { --pc-poll-color: #3f8cff; }
.pc-poll-choice[data-index="2"] { --pc-poll-color: #ff3fa4; }
.pc-poll-choice[data-index="3"] { --pc-poll-color: #f7bd55; }
.pc-poll-choice[data-index="4"] { --pc-poll-color: #42d392; }
.pc-poll-choice[data-index="5"] { --pc-poll-color: #a18cff; }

.pc-poll-choice-head,
.pc-poll-choice-stats {
  justify-content: center;
  text-align: center;
}

.pc-poll-choice-stats {
  order: -1;
}

.pc-poll-choice-percent {
  color: var(--pc-poll-color);
  font-size: 40px;
  line-height: 1;
}

.pc-poll-choice-title {
  font-size: 15px;
}

.pc-poll-choice-votes,
.pc-poll-points,
.pc-poll-total {
  display: none;
}

.pc-poll-choice-bar {
  width: 100%;
  height: 6px;
}

/* Победитель остаётся своего цвета, но обводится. */
.pc-poll-choice[data-winner="true"] {
  outline: 2px solid var(--pc-poll-win);
}

Без плашки

Текст поверх игры без фона: подходит, когда на сцене уже есть своя рамка.

html,
body {
  margin: 0;
  background: transparent;
  overflow: hidden;
}

.pc-poll {
  gap: 8px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
  color: #ffffff;
  font-family: "Inter", system-ui, sans-serif;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.9);
}

.pc-poll-title {
  font-size: 21px;
}

.pc-poll-choice-bar {
  height: 6px;
  background: rgba(255, 255, 255, 0.18);
}

.pc-poll-choice-votes,
.pc-poll-total {
  display: none;
}

/* Итог виден без чтения: победитель загорается, остальные почти исчезают. */
.pc-poll[data-result="winner"] .pc-poll-choice[data-winner="false"],
.pc-poll[data-result="tie"] .pc-poll-choice[data-winner="false"] {
  opacity: 0.25;
}

.pc-poll-choice[data-winner="true"] {
  filter: drop-shadow(0 0 12px rgba(66, 211, 146, 0.55));
}
Промпт для AI-агента, который сделает свой CSS

Скопируйте текст ниже в ChatGPT, Codex или другой AI-инструмент, если хотите получить оформление под свою сцену.

Сделай готовый OBS Custom CSS для Browser Source с голосованием (опросом Twitch) PulseCaster.

Контекст:
- OBS открывает прозрачную HTML-страницу с опросом Twitch.
- Я не могу менять HTML и не хочу добавлять JavaScript.
- Можно использовать только CSS.
- У страницы уже есть оформление по умолчанию, завёрнутое в :where() с нулевым весом,
  поэтому мои обычные правила его перебивают без !important.
- HTML-структура такая:

<div class="pc-poll"
     data-status="active"
     data-visible="true"
     data-choices="3"
     data-votes="true"
     data-hurry="false"
     data-result="">
  <div class="pc-poll-head">
    <span class="pc-poll-title">Во что играем после перерыва?</span>
    <span class="pc-poll-timer" data-seconds="95">01:35</span>
  </div>
  <span class="pc-poll-points">Дополнительный голос — 250 баллов</span>
  <span class="pc-poll-note"></span>
  <ol class="pc-poll-choices">
    <li class="pc-poll-choice" data-index="1" data-leader="true" data-winner="false"
        data-percent="54.0" style="--pc-poll-percent: 53.95;">
      <span class="pc-poll-choice-head">
        <span class="pc-poll-choice-title">Doom</span>
        <span class="pc-poll-choice-badge" hidden>Победитель</span>
      </span>
      <span class="pc-poll-choice-stats">
        <span class="pc-poll-choice-percent">54%</span>
        <span class="pc-poll-choice-votes">41 голос</span>
      </span>
      <span class="pc-poll-choice-bar"><span class="pc-poll-choice-fill"></span></span>
    </li>
  </ol>
  <span class="pc-poll-total">Всего 76 голосов</span>
</div>

Что меняется само:
- data-status равен active, completed (время вышло) или terminated (завершено досрочно);
- data-visible становится false, когда срок показа вышел, и страница сама убирает голосование со сцены;
- data-result после конца равен winner, tie (ничья) или no_votes (никто не проголосовал);
- data-leader="true" стоит у лидирующего варианта, пока голосование идёт;
- data-winner="true" стоит у победителя после конца; при ничьей — у всех, кто поделил первое место;
- data-index — номер варианта по порядку, от 1 до 5;
- data-hurry="true" появляется в последние десять секунд;
- data-votes="false" появляется, если число голосов выключено в кабинете;
- переменная --pc-poll-percent на варианте всегда равна его доле голосов;
- .pc-poll-note содержит подпись итога, .pc-poll-points — подсказку про голос за баллы;
- значок .pc-poll-choice-badge пишет «Победитель», а при ничьей — «Ничья».

Задача:
- Сделай CSS для OBS Custom CSS.
- Фон должен быть прозрачным.
- Текст должен хорошо читаться поверх игры или камеры.
- Нужен стиль: [опиши стиль: неон, минимализм, ретро, киберпанк, спортивное табло и т.д.].
- Цвета сцены: [впиши основные цвета].
- Размер источника OBS: [например 620x480].
- Сколько вариантов обычно: [например два-три или до пяти].
- Шрифт: [системный или file:///путь/к/моему-шрифту.woff2].

Требования к ответу:
- Верни только готовый CSS.
- Не используй внешние URL, кроме моего file:/// шрифта, если я его указал.
- Используй селекторы .pc-poll, .pc-poll-title, .pc-poll-timer, .pc-poll-note,
  .pc-poll-choice, .pc-poll-choice-title, .pc-poll-choice-percent,
  .pc-poll-choice-bar, .pc-poll-choice-fill и атрибуты data-*.
- Не скрывай .pc-poll-choice-title и .pc-poll-choice-percent.
- Не пытайся скрывать голосование сам: это делает страница через data-visible.
- Ширину полосы бери из var(--pc-poll-percent), не из фиксированных значений.
- Сделай отдельный вид для data-result="winner", data-result="tie" и data-result="no_votes".
- Учитывай, что вариантов может быть от двух до пяти.
- Добавь font-variant-numeric: tabular-nums, чтобы проценты не дёргались.
- Если добавляешь анимацию, сделай её медленной и ненавязчивой.

Что делать, если на сцене пусто

Признак Причина Что сделать
Источник пуст всегда виджет выключен или ссылка заменена включите виджет во вкладке Сцена OBS и проверьте адрес в OBS
Голосование видно, проценты стоят нет права channel:read:polls переподключите Twitch-аккаунт владельца
Голосование не появилось после запуска из Twitch события EventSub не дошли откройте раздел Голосования — вход в него сверяет состояние с Twitch
Кнопки пульта недоступны нет права channel:manage:polls переподключите Twitch-аккаунт владельца
Запустить не нажимается на канале уже идёт голосование завершите текущее
Twitch отказывает при запуске канал не Affiliate и не Partner опросы Twitch такому каналу недоступны
Итоги пропали сразу голосование убрали без итогов или задержка 0 проверьте настройку во вкладке Сцена OBS

Безопасность

  • Не публикуйте OBS-ссылку в чате или описании канала: по ней видно голосование канала.
  • Не показывайте ссылку на стриме — в ней есть токен.
  • Если ссылка утекла, нажмите Заменить ссылку: старый адрес сразу перестанет открываться.
  • Если источник больше не нужен, нажмите Выключить виджет: заготовки и настройки останутся.