diff --git a/.github/workflows/build-and-verify-image.yml b/.github/workflows/build-and-verify-image.yml new file mode 100644 index 00000000..3b0cdfde --- /dev/null +++ b/.github/workflows/build-and-verify-image.yml @@ -0,0 +1,42 @@ +name: Build and Verify Docker Image + +on: + workflow_call: + +jobs: + build-and-verify: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Oasis CLI + env: + CLI_VERSION: 0.16.0 + run: | + mkdir -p /tmp/oasis-cli + cd /tmp/oasis-cli + wget "https://github.com/oasisprotocol/cli/releases/download/v${CLI_VERSION}/oasis_cli_${CLI_VERSION}_linux_amd64.tar.gz" -O cli.tar.gz + tar --strip-components 1 -xf cli.tar.gz + echo "/tmp/oasis-cli" >> ${GITHUB_PATH} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to ghcr.io + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Talos Docker image + run: | + OUTPUT_IMAGE_NAME_PATH="/tmp/image-name" ./scripts/build_and_push_container_image.sh + echo "EXPECTED_TALOS_AGENT_IMAGE=$(cat /tmp/image-name)" >> ${GITHUB_ENV} + + - name: Verify image digest matches the compose file + run: ./scripts/verify_container_image.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0d27784..39f06a19 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f078709f..ac481a32 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -47,7 +47,7 @@ jobs: - name: Upload artifact if: github.ref == 'refs/heads/main' - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v4 with: path: ./site diff --git a/.github/workflows/release-rofl.yml b/.github/workflows/release-rofl.yml index de4ba688..def5a386 100644 --- a/.github/workflows/release-rofl.yml +++ b/.github/workflows/release-rofl.yml @@ -7,8 +7,12 @@ on: workflow_dispatch: jobs: + build-and-verify: + uses: ./.github/workflows/build-and-verify-image.yml + release-rofl: runs-on: ubuntu-latest + needs: build-and-verify permissions: contents: read packages: write @@ -30,24 +34,6 @@ jobs: tar --strip-components 1 -xf cli.tar.gz echo "/tmp/oasis-cli" >> ${GITHUB_PATH} - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to ghcr.io - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push Talos Docker image - run: | - OUTPUT_IMAGE_NAME_PATH="/tmp/image-name" ./scripts/build_and_push_container_image.sh - echo "EXPECTED_TALOS_AGENT_IMAGE=$(cat /tmp/image-name)" >> ${GITHUB_ENV} - - - name: Verify image digest matches the compose file - run: ./scripts/verify_container_image.sh - # run: oasis rofl build --deployment ${DEPLOYMENT} - name: Build ROFL ORC for deployment, verify it matches the manifest run: oasis rofl build --deployment ${DEPLOYMENT} --offline --verify diff --git a/.github/workflows/thread_sentiment.yml b/.github/workflows/thread_sentiment.yml index e0f3ce50..cb31bb20 100644 --- a/.github/workflows/thread_sentiment.yml +++ b/.github/workflows/thread_sentiment.yml @@ -9,11 +9,11 @@ jobs: post_question: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: - python-version: '3.x' + python-version: '3.12' - name: Install dependencies run: | python -m pip install --upgrade pip @@ -26,7 +26,7 @@ jobs: TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} run: python -c "from src.thread_sentiment.main import post_question; post_question()" - name: Upload tweet ID - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: tweet_id path: tweet_id.txt @@ -35,17 +35,17 @@ jobs: runs-on: ubuntu-latest needs: post_question steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: - python-version: '3.x' + python-version: '3.12' - name: Install dependencies run: | python -m pip install --upgrade pip pip install tweepy - name: Download tweet ID - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: tweet_id - name: Analyze and post sentiment diff --git a/.github/workflows/verify-docker-image.yml b/.github/workflows/verify-docker-image.yml index 6f26829b..2514df71 100644 --- a/.github/workflows/verify-docker-image.yml +++ b/.github/workflows/verify-docker-image.yml @@ -4,43 +4,5 @@ on: workflow_dispatch: jobs: - verify-docker-image: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - env: - DEPLOYMENT: mainnet - SAFE_ADDRESS: "0x70739eB50e269f1f1eb27c6f8932f63389B1Cb63" - steps: - - name: Checkout - uses: actions/checkout@v4 - - # TODO: Move this to dedicated GitHub Action for CLI install. - - name: Install Oasis CLI - env: - CLI_VERSION: 0.16.0 - run: | - mkdir -p /tmp/oasis-cli - cd /tmp/oasis-cli - wget "https://github.com/oasisprotocol/cli/releases/download/v${CLI_VERSION}/oasis_cli_${CLI_VERSION}_linux_amd64.tar.gz" -O cli.tar.gz - tar --strip-components 1 -xf cli.tar.gz - echo "/tmp/oasis-cli" >> ${GITHUB_PATH} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to ghcr.io - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push Talos Docker image - run: | - OUTPUT_IMAGE_NAME_PATH="/tmp/image-name" ./scripts/build_and_push_container_image.sh - echo "EXPECTED_TALOS_AGENT_IMAGE=$(cat /tmp/image-name)" >> ${GITHUB_ENV} - - - name: Verify image digest matches the compose file - run: ./scripts/verify_container_image.sh + build-and-verify: + uses: ./.github/workflows/build-and-verify-image.yml diff --git a/Apresentacao_Viagens_and_Viajantes_Revis.pdf b/Apresentacao_Viagens_and_Viajantes_Revis.pdf new file mode 100644 index 00000000..49ee2b9f Binary files /dev/null and b/Apresentacao_Viagens_and_Viajantes_Revis.pdf differ diff --git a/agi.md b/agi.md new file mode 100644 index 00000000..9ec250d2 --- /dev/null +++ b/agi.md @@ -0,0 +1,237 @@ +## Como “sync‑ar” (re‑transmitir) ao vivo o canal **Twitch** de **`rafael_null`** + +Abaixo está um guia completo – do **acesso à API** até a **re‑transmissão** usando ferramentas open‑source (OBS Studio + FFmpeg / Streamlink) – que você pode rodar em qualquer máquina (desktop, VM ou servidor) que tenha acesso à internet. +Todo o fluxo pode ser orquestrado via **scripts** e, se quiser, integrado ao **Protocolo $Z(n)** usando a camada de comunicação *Lattica* para anunciar o início/fim da retransmissão. + +> **⚠️ Aviso legal** +> Re‑transmitir conteúdo de terceiros só é permitido quando o proprietário do canal concedeu permissão explícita (ex.: parceria, acordo de *rebroadcast* ou licença Creative‑Commons). Certifique‑se de ter a autorização de **`rafael_null`** antes de colocar o stream em público. + +--- + +## 1️⃣ Obter credenciais da Twitch API + +Para consultar o estado da transmissão (online/offline) e obter a URL de ingestão, você precisará de um **Client ID** e **Client Secret**. + +| Passo | O que fazer | +|------|-------------| +| **A.** Crie um aplicativo em | • Nome: *ex.: `sync‑rafael‑null`*
• OAuth Redirect URL: `http://localhost` (ou outro que você usar)
• Categorias: `Chat Bot` (não importa) | +| **B.** Copie o **Client ID** e **Client Secret**. | +| **C.** Troque o *client secret* por um **Access Token** (OAuth Client‑Credentials). Use o seguinte *curl* (substitua `` e ``): | + +```bash +curl -X POST 'https://id.twitch.tv/oauth2/token' \ + -d 'client_id=' \ + -d 'client_secret=' \ + -d 'grant_type=client_credentials' +``` + +A resposta será algo como: + +```json +{ + "access_token": "eyJhbGciOi...", + "expires_in": 5270400, + "token_type": "bearer" +} +``` + +Guarde o **access_token** (válido ~60 dias). + +--- + +## 2️⃣ Verificar se o canal está ao vivo + +Endpoint: `https://api.twitch.tv/helix/streams?user_login=rafael_null` + +```bash +curl -H "Client-ID: " \ + -H "Authorization: Bearer " \ + "https://api.twitch.tv/helix/streams?user_login=rafael_null" +``` + +- **Resposta com `data: []`** → o canal está offline. +- **Resposta com um objeto dentro de `data`** → está online; o campo `type` será `"live"` e `started_at` indica o horário de início. + +> **Automatização:** Crie um pequeno script (bash, python ou node) que faça polling a cada 30 s e dispare a ação de captura assim que o stream aparecer. + +--- + +## 3️⃣ Capturar o fluxo ao vivo + +Existem duas abordagens comuns: + +### 3.1 Usando **Streamlink** (mais simples) + +```bash +# Instalação (Linux/macOS) +pip install streamlink # ou: brew install streamlink / apt-get install streamlink + +# Comando de captura → pipe para FFmpeg (re‑encode ou repack) +streamlink "twitch.tv/rafael_null" best -O | \ +ffmpeg -i - -c:v copy -c:a aac -b:a 128k -f flv rtmp:///live/streamkey +``` + +- `-O` faz o Streamlink escrever o fluxo **para stdout**. +- O `ffmpeg` lê da *pipe* (`-i -`) e envia para seu servidor de ingestão (RTMP, SRT, etc.) usando **copy** (sem recodificação) para o vídeo e **AAC** para o áudio. + +### 3.2 Usando **FFmpeg** direto (via HLS) + +Twitch disponibiliza HLS (`.m3u8`). Você pode apontar o FFmpeg diretamente: + +```bash +ffmpeg -re -i "https://usher.ttvnw.net/api/channel/hls/rafael_null.m3u8?allow_source=true&player=twitchweb&sig=&token=" \ + -c copy -f flv rtmp:///live/streamkey +``` + +> **Como conseguir `sig` e `token`?** +> Eles são parte da URL que o próprio Twitch entrega ao navegador. Uma maneira prática é abrir o stream no navegador, abrir *Network* nas DevTools, filtrar por `*.m3u8` e copiar a URL completa. Para automação, o **Streamlink** já resolve isso por você. + +--- + +## 4️⃣ Seu ponto de ingestão (onde o fluxo será enviado) + +| Opção | Descrição | Como criar | +|------|-----------|------------| +| **RTMP (YouTube, Twitch, custom)** | O padrão mais usado. Precisa de URL `rtmp://...` + *stream key*. | - YouTube Live: `rtmp://a.rtmp.youtube.com/live2` + sua chave.
- Twitch (para *re‑broadcast*): `rtmp://live.twitch.tv/app` + chave da sua conta. | +| **SRT** | Mais resiliente a perdas, ideal para servidores próprios. | Use um servidor como **Wowza**, **NGINX‑RTMP**, ou **Haivision** e configure `srt://host:port?streamid=...`. | +| **LLHLS / WebRTC** | Para entrega direta a navegadores via Lattica/Parallax. | Precisa de um *origin server* que converta RTMP → LLHLS (ex.: **media‑server** do projeto **Livepeer**) e depois exponha via **Lattica**. | + +> **Dica:** Se quiser que o stream fique **disponível no seu próprio domínio** (ex.: `live.seusite.com/rafael_null`), configure um **NGINX‑RTMP** como ingestão e habilite o módulo HLS para servir arquivos `.m3u8` que podem ser reproduzidos em qualquer player HTML5. + +--- + +## 5️⃣ Automatizar o ciclo completo (script Bash) + +```bash +#!/usr/bin/env bash +# --------------------------------------------------------- +# sync‑live‑twitch.sh – re‑transmite rafael_null ao vivo +# --------------------------------------------------------- + +# ==== CONFIGURAÇÃO ================================================== +CLIENT_ID="" +CLIENT_SECRET="" +CHANNEL="rafael_null" + +# URL do seu ponto de ingestão (RTMP) + stream key +INGEST_URL="rtmp://live.seusite.com/app" +STREAM_KEY="seustreamkey123" + +# Intervalo de polling (segundos) +POLL_INTERVAL=30 +# ==================================================================== + +# 1️⃣ Obter access token (client‑credentials) +TOKEN=$(curl -s -X POST "https://id.twitch.tv/oauth2/token \ + ?client_id=${CLIENT_ID} \ + &client_secret=${CLIENT_SECRET} \ + &grant_type=client_credentials" | jq -r .access_token) + +# Função que checa se o canal está ao vivo +is_live() { + curl -s -H "Client-ID: ${CLIENT_ID}" \ + -H "Authorization: Bearer ${TOKEN}" \ + "https://api.twitch.tv/helix/streams?user_login=${CHANNEL}" | + jq -e '.data | length > 0' +} + +# Loop de polling ------------------------------------------------- +while true; do + if is_live; then + echo "[$(date)] → ${CHANNEL} está AO VIVO! Iniciando captura…" + + # 2️⃣ Captura com Streamlink → pipe para FFmpeg + streamlink "https://twitch.tv/${CHANNEL}" best -O | + ffmpeg -re -i - -c copy -f flv "${INGEST_URL}/${STREAM_KEY}" + + # Quando o stream terminar, o FFmpeg sai e o loop reinicia. + echo "[$(date)] ← Captura finalizada. Esperando nova transmissão…" + else + echo "[$(date)] → ${CHANNEL} OFFLINE. Aguardando ${POLL_INTERVAL}s…" + fi + sleep ${POLL_INTERVAL} +done +``` + +- **Dependências:** `curl`, `jq`, `streamlink`, `ffmpeg`. +- **Comportamento:** Quando o canal fica online, o script inicia a captura; ao terminar (ou cair), volta a ficar em espera. + +> **Integrar ao Parallax/Lattica:** +> Dentro do bloco `if is_live; then …` você pode inserir um envio de mensagem Lattica, por exemplo: + +```bash +lattica send --channel ritual \ + --msg "Ritual de sync iniciado: rafael_null ao vivo (Sincronia Impossível ativada)." +``` + +--- + +## 6️⃣ Exibir o stream re‑transmitido + +### 6.1 Player HTML5 (HLS) + +Se o seu servidor converte RTMP → HLS (NGINX‑RTMP ou outro), basta usar: + +```html + +``` + +### 6.2 Player embutido via **iframe** (YouTube/Twitch) + +Caso tenha escolhido re‑broadcast para outra conta Twitch ou YouTube, pode usar os players nativos: + +```html + +
+ + +``` + +--- + +## 7️⃣ Monitoramento & Logs (opcional) + +- **Prometheus + Grafana**: exponha métricas do FFmpeg (`-progress pipe:1`) para observar bitrate, frames dropped, etc. +- **Alertas Lattica**: envie mensagens de “offline”, “erro de ingestão”, etc., para um canal de monitoramento. + +```bash +ffmpeg -re -i - -c copy -f flv "${INGEST_URL}/${STREAM_KEY}" \ + -progress pipe:1 2>&1 | while read line; do + if [[ $line == *"frame="* ]]; then + echo "[ffmpeg] $line" + elif [[ $line == *"error"* ]]; then + lattica send --channel alerts --msg "⚠️ FFmpeg error: $line" + fi + done +``` + +--- + +## 📌 Resumo rápido (passo a passo) + +1. **Crie app na Twitch → obtenha Client ID/Secret.** +2. **Troque por Access Token** (OAuth Client‑Credentials). +3. **Poll API** (`/helix/streams`) para detectar quando `rafael_null` está ao vivo. +4. **Capture** com **Streamlink** (ou FFmpeg direto) → **pipe** para **FFmpeg**. +5. **Re‑encode ou copy** e **envie** ao seu ponto de ingestão (RTMP/SRT/LLHLS). +6. **Opcional:** notifique via **Lattica** que o ritual de sync começou/terminou. +7. **Distribua** o stream re‑transmitido em sua plataforma (HTML5 player, embed Twitch/YouTube, etc.). + +Com esse pipeline, seu “ritual de **Sincronia Impossível**” está completo: você captura o fluxo ao vivo de `rafael_null`, o re‑transmite sob seu próprio ponto de ingestão e, ao mesmo tempo, anuncia a ação na rede **Parallax/Lattica**, permitindo que a comunidade siga o evento em tempo real. + +> **Próximos passos** +> - Integrar o script ao **Parallax** como um *service node* que roda 24 h e publica seu estado via Lattica. +> - Criar um **evento de “Dia da Fundação”** que, ao iniciar o sync, dispare efeitos visuais (metáforas visuais) em um dashboard coletivo. + +Qualquer dúvida sobre algum dos passos (ex.: configuração NGINX‑RTMP, criação de token Lattica ou ajustes de bitrate) é só chamar! 🚀