name: inverse layout: true class: center, middle, inverse --- name: impact layout: true class: center, middle, impact, content --- name: title layout: true class: title center --- name: content layout: true --- template: title name: main-title .content[
### Nos bastidores do podcast .small[ ou "como criar e manter um podcast a custo zero com Software Livre" ] ] --- # Sobre mim ## Tiago Carreira .left-column[ - Lisboa 🇵🇹 → Rio de Janeiro 🇧🇷 - Engenheiro DevOps
- Hobbies: .small[ - Desporto (correr, bicicleta, escalada) - Música (clarinete, flauta, piano, guitarra) - Produção audiovisual (fotografia, vÃdeo, **podcast**) - Open Source
] ] .rigth-column[ .center.pic-circle[
] .center.no-bullets.tiny[ **site:** tiago.carreira.pw
**telegram:** @tcarreira
**github:** github.com/tcarreira
**twitter:** @tiagogcarreira ] ] --- layout: false template: impact name: agenda # Agenda - O que é um podcast - Gravação e captura - Edição sonora - Website - Publicação - Automatização --- # Opções, demasiadas opções... .center.comparison.small[ | | Contratar
serviço profissional | Plataforma para
podcasters | Alojamento multimedia
(eg: soundcloud) | Self-Hosted | Marmita de Redon | |-------------------|:------------------------------:|:----------------------------------:|:--------------------------------------------------------:|:-----------------------------------------------:|:-------------------------------------------------------------------------:| | Material Gravação | ✓✓ | ? | ? | ? | ? | | Marca/Tema | ✓✓ | ✓! | ✓ | ✓ | ✓ | | Edição áudio | ✓✓ | ✓! | ✓ | ✓ | ✓ | | Website | ✓✓ | ✓! | ✓! | ✓ | ✓ | | Alojamento | ✓✓ | ✓✓ | ✓! | ✓ | ✓ | | Analytics | ✓✓ | ✓✓ | ✓✓ | ✓✓ | ✓ | | Monetização | ✓✓ | ✓/✓✓ | ✓ | ✓ | ? | | Controlo total | ✓✓ | ✗ | ✗ | ✓ | ✓ | | | | | | | | | Custos | $$$$$ | 0-$$ | 0-$ | $$ | 0 | | Tempo Investido | 🕒 | 🕒 | 🕒 | 🕒🕒 | 🕒🕒🕒 | | Manutenção ($/t) | $$$$ / 🕒 | 0-$$ / 🕒 | $$ / 🕒 | $$ / 🕒 | 0 / 🕒 | ] ??? ✓✓ - Feito pelo serviço ✓! - IncluÃdo no serviço, mas não é ideal ✓ - DisponÃvel (feito manualmente) ✗ - IndisponÃvel \* os custos não incluem o material de gravação, por ser comum a todos os serviços. [1] Paid Podcasters Platforms: Acast, Blubrry, Buzzprout, Captivate, Castos, Descript, Podbean, Simplecast, Speaker, Transistor, etc... [2] Free Podcasters Platforms:
Anchor
, Breaker, Castbox, etc... --- template: impact name: whatis # O que é um podcast --- # Do podcast ao ouvinte .left-column[ 1. Ouvinte usa um Podcatcher (Spotify, iTunes, AntennaPod, cPod, gPodder, VLC, etc...) 1. Podcatcher lê **Feed RSS** do podcast 1. Podcatcher extrai metadados sobre o podcast e todos os episódios 1. Podcatcher faz **download do áudio** através do link disponibilizado no Feed RSS 1. Ouvinte ouve o episódio :) ] -- .right-column[ .tiny[ ```
Marmita de Redon
https://marmita.pt/
Um podcast sobre os anos 90 e 2000
pt-pt
weekly
https://marmita.pt/images/thumbnail.jpg
#20 Rapar O Tacho
https://marmita.pt/post/s01e20/
Fri, 29 Jan 2021 00:00:00 +0000
Chegamos ao fim desta temporada. O que foi e o que vem depois?
É verdade, chegamos hoje ao episódio 20, no qual marcamos ...... ]]>
20
0:17:36
... ``` ]] ??? - RSS Feed - Audio alojado em servidores --- # Componentes de um podcast .center[ ## Essenciais - Conteúdo - Captação - Ficheiros áudio - Alojamento - Feed RSS ] .left-column.center[ ## Recomendados - Site oficial - Redes sociais - Marca - EstatÃsticas ] .right-column.center[ ## Opcionais - Periodicidade - Monetização - Um plano ] --- template: impact name: gravacao # Gravação e Captura --- # Microfones .left-column[ ## Condensadores - som mais detalhado e nÃtido - maior captação de baixas frequências (graves) - normalmente precisam de _phantom power_ .center[
.tiny[ "In Front of a Microphone" by [Dejan Krsmanovic](https://www.flickr.com/photos/dejankrsmanovic/44223347312/) ] ] ] .right-column[ ## Dinâmicos - melhores cancelamento de ruÃdo de fundo - mais resistentes - maior variação de volume sem distorção .center[
.tiny[ "Shure SM58" by [ElÃas Gómez](https://www.flickr.com/photos/egomez/3519651938/) ] ] ] --- # Microfones - Conexões - P2/P3 - ligam diretamente ao _smartphone_ ou à porta de microfone do computador - XLR - ligam a uma interface ou mesa de som - USB - ligam diretamente ao computador .center[
] .tiny[ - "3.5mm" by [Lee Bennett](https://flic.kr/p/4v9Zrp) - "XLR Audio Connector for microphone cable" by [Marco Verch Professional](https://flic.kr/p/2jSFPmE) - "Samson Q2U USB/XLR Dynamic Microphone" by [Samson](http://www.samsontech.com/samson/products/microphones/usb-microphones/q2u/) ] ??? - P2/P3 - Pior qualidade. Além disso, a porta de microfone de um computador é frequentemente de fraca qualidade - XLR - ligam a uma interface ou mesa de som - USB - ligam diretamente ao computador --- # Captação .left-column[ - Correto uso do microfone - distância - pop filter - suporte - Ambiente à volta - espaço onde se grava - ruÃdos internos - ruÃdos externos ] .right-column.center[
.tiny[ "Podcasting Mic on Shock Mount" by [Kertojan ääni](https://flic.kr/p/291UTUw) ] ] ??? - Sala onde se grava: Tamanho e forma da sala, distância à s paredes, presença de objetos, ... tudo o que está à volta do microfone influencia o "ambiente" de gravação. - RuÃdos "cá dentro": Coisas como teclado, ruÃdo do computador (ventoÃnha ligada), ar condicionado, cadeira onde estamos sentados que faz barulho quando nos mexemos, manusear objetos que façam ruÃdo (eg: papel), vibrações (ou pancadas) na mesa, ... - RuÃdos "lá fora": Isolamento das portas e janelas, pancadas nas paredes (obras do vizinho), ... --- # Captação - Como foi feito (sem custos) .left-column[ ## Gravação com o Smartphone \+ Melhor custo (zero) \+ AcessÃvel \+ "suficiente" para publicar um podcast \- não tem qualidade profissional ] .right-column.center[
] --- template: impact name: edição # Edição sonora --- # Processo .left-column[ - Importar todos as faixas - Sincronizar falas (com ajuda de um _master_) - "Corte e costura" - pré-filtros - silenciar ruÃdos - remover sobreposições de falas - tornar interrupções mais naturais - Masterização - Equalização - Filtros - Compressão - Modelação 8D* - Rederização ] .right-column.center[
] -- .right-column[ ### *Modelação 8D - Disposição espacial dos hosts
(Cada host tem um lugar espacial diferente) - ImpercetÃvel em Mono - Feito de forma automática através de uma [macro no audacity](https://github.com/marmita-de-redon/audacity-macros) - Isolamento estéreo de cada faixa - Diferentes amplitudes em cada canal - Atrasos artificiais em canais isolados ] --- template: impact name: website # Website --- # Necessidade de um website .left-column[ - Necessidades - visualmente simples - listar artigos (episódios) com imagem - suporte mobile - suporte de RSS feeds para podcast - nice-to-have: tema escuro ] --- # Static HTML / Headless CMS - Hugo .left-column[ - Necessidades - visualmente simples - listar artigos (episódios) com imagem - suporte mobile - suporte de RSS feeds para podcast - nice-to-have: tema escuro - Hugo - geração de HTML estático - tema: [hugo-redon-podcast](https://github.com/marmita-de-redon/hugo-redon-podcast)
- fork de [hugo clarity](github.com/chipzoller/hugo-clarity) - baseado no [VMware Clarity design](https://clarity.design/) - Alojamento com Github Pages ] .right-column.center[
Clarity Design System
] --- # Layout .center[
] --- # Hugo .left-column.tiny[ ``` . ├── config │ └── _default │ └── menus │ └── menu.pt.toml ├── config.toml ├── content │ ├── _index.md │ ├── contactos.md │ ├── feed │ │ └── podcast │ │ └── _index.md │ ├── post │ │ ├── _index.md │ │ ├── s01e00.md │ │ ├── s01e01.md │ │ ├── s01e02.md │ │ ├── s01e03.md │ │ ├── s01e04.md │ │ ├── s01e05.md │ │ └── ... │ ├── sobre.md │ └── subscrever.md ├── data │ └── social.yaml └── ... ``` ] .right-column.tiny[ ```yaml +++ title = "#16 Brinquedos (parte 1)" itunes_title = "Brinquedos (parte 1)" episode = 16 podcast_file = "https://media.blubrry.com/marmitaderedon/archive.org/download/marmitaderedon-s01e16/s01e16-brinquedos_1.mp3" podcast_duration = "0:19:30" podcast_bytes = "28091404" author = "Marmita de Redon" date = "2021-01-01" description = "Pega-monstros, berlindes, tazos, tragabolas... Qual era o vosso brinquedo de eleição? " thumbnail = "images/s01e16.jpg" featured = false aliases = ["s01e16", "S01E16", "16"] +++ Na altura em que a internet ainda era uma miragem, esta malta brincava com coisas analógicas, feitas de um plástico duvidoso dos anos 90. Yo-yo’s ou diábolos entretinham-nos por horas e os pega-monstros eram o terror das raparigas no recreio. ## Atribuição e licenças - **Produzido por:** Joana Sanches, Marco Seabra, Tiago Carreira e Tiago MaurÃcio. - **Editado por:** Tiago Carreira. - **Música**: [Redon dos 90](https://archive.org/details/redon90) de Tiago Carreira, está licenciada nos termos da [Licença Creative Commons - Atribuição 4.0 Internacional](http://creativecommons.org/licenses/by/4.0/). Este episódio está licenciado nos termos da [Licença Creative Commons - Atribuição-SemDerivações 4.0 Internacional](https://creativecommons.org/licenses/by-nd/4.0/) (CC BY-ND 4.0). ``` ] --- # Alojamento do website - Github Pages .left-column[ - suporta html estático (e mais algumas coisas) - (relativamente) fácil - permite domÃnio próprio - HTTPS automático (mesmo para domÃnio próprio) - sem manutenção - gratuito
### Alojamento de ficheiros áudio .center[
] ] .right-column[
] --- template: impact name: publicacao # Publicação --- # Fluxo de Publicação .left-column[ - gravar - editar - criar os textos para a descrição - criar novo thumbnail - upload dos ficheiros para o Archive.org - criar novo vÃdeo (para youtube) - criar novo artigo (markdown) - atualizar o site ] --- # Fluxo de Publicação .center[
] --- # Fluxo de Publicação - Automatizado .left-column[ - gravar - editar - criar os textos para a descrição - .not[criar novo thumbnail] - .not[upload dos ficheiros para o Archive.org] - .not[criar novo vÃdeo (para youtube)] - .not[criar novo artigo (markdown)] - .not[atualizar o site] ] .right-column[ - gravar - editar - criar os textos para a descrição - **chamar um script que automatiza tudo** * .tiny[
\* com exceção das redes sociais ] ] ??? limitações na API do youtube, mas existe solução https://github.com/ubuntupodcast/podpublish#youtube-api --- template: impact name: automatizacao # Automatização --- # Shell script - claro, porque não... ```bash function .main() { .check_pre_requisites .print_and_check_info .generate_thumbnail .upload_audio_to_archive_org .render_video .upload_to_youtube .create_markdown_file .commit_and_push_website } ``` --- # Automatização - criação do thumbnail `.generate_thumbnail` .small[ ``` python create_thumbnail.py "../images/base_thumbnail.png" "${THUMBNAIL_PATH}" "#1 TÃtulo do Episódio" ```
`create_thumbnail.py` ```python img = Image.open(image_source) img_rgb = img.convert('RGB') draw = ImageDraw.Draw(img_rgb) font = ImageFont.truetype("font.ttf", 300) w, h = draw.textsize(text, font=font) position = (center_x-w/2, center_y-h/2) draw.text(position, text, align="center", fill=color, font=font) img_rgb = img_rgb.resize((1024,1024), resample=Image.BICUBIC) img_rgb.save(image_dest) ``` ]
--- # Automatização - upload do áudio `.upload_audio_to_archive_org` .small[ ``` ./ia upload "${ARCHIVE_ORG_IDENTIFIER}" \ "${AUDIO_PATH}" \ "${THUMBNAIL_PATH}" \ --metadata="mediatype:audio" \ --metadata="language:por" \ --retries 5 ``` ] --- # Automatização - renderização do vÃdeo `.render_video` .small[ ``` ffmpeg \ -loop 1 \ -i "${THUMBNAIL_PATH}" \ -i "${AUDIO_PATH}" \ -shortest \ -acodec copy \ "${VIDEO_PATH}" -y ``` ] --- # Automatização - upload para youtube `.upload_to_youtube` .small[ ``` jq -n -f "${YOUTUBE_TEMPLATE_JSON_PATH}" \ --arg title "${YOUTUBE_TITLE}" \ --arg description "${BODY_MD_TEXT}$(echo -e "\n\n")${FOOTER_MD_TEXT}" \ --arg privacystatus "${YOUTUBE_PRIVACY_STATUS}" \ --arg license "${YOUTUBE_LICENCE}" \ | shoogle execute -c "${GOOGLE_CREDENTIALS_PATH}" youtube:v3.videos.insert - -f "${VIDEO_PATH}" ``` ] .left-column.tiny[ ```json { "part": "snippet,status", "body": { "snippet": { "title": $title, "description": $description }, "status": { "license": $license, "privacyStatus": $privacystatus, "selfDeclaredMadeForKids": false } } } ``` ] .right-column.small[ nota: O shoogle usa uma API do youtube que não permite fazer agendamento de publicações.
Mas parece haver soluções por aÃ: https://github.com/ubuntupodcast/podpublish#youtube-api ] --- # Automatização - criação do novo episódio `.create_markdown_file` .small[ .left-column[ ``` EPISODE_NUMBER=16 # number, not string TITLE="Brinquedos (parte 1)" # title without episode number. DESCRIPTION="Pega-monstros, berlindes, tazos, tragabolas... Qual era o vosso brinquedo de eleição? " # Short description AUDIO_PATH="../rendered/s01e16-brinquedos_1.mp3" # this file will be uploaded to archive.org PUBLISHED_AT="2021-01-01" # publish date. eg: 2020-01-31 BODY_MD_TEXT=" Na altura em que a internet ainda era uma miragem, esta malta brincava com coisas analógicas, feitas de um plástico duvidoso dos anos 90. Yo-yo’s ou diabolos entretinham-nos por horas e os pega-monstros eram o terror das raparigas no recreio. " ``` ``` echo "${MARKDOWN_TEMPLATE}" >"${_markdown_post_file}" ``` ] .right-column[ ``` MARKDOWN_TEMPLATE="+++ title = \"#${EPISODE_NUMBER} ${TITLE}\" itunes_title = \"${TITLE}\" episode = ${EPISODE_NUMBER} podcast_file = \"${AUDIO_URL}\" podcast_duration = \"${AUDIO_DURATION}\" podcast_bytes = \"${AUDIO_BYTES}\" author = \"${AUTHOR}\" date = \"${PUBLISHED_AT}\" description = \"${DESCRIPTION}\" thumbnail = \"${THUMBNAIL_URL}\" featured = ${WEBSITE_FEATURED} aliases = [\"${_SxxExx}\", \"${EPISODE_NUMBER}\"] +++ ${BODY_MD_TEXT} ${FOOTER_MD_TEXT}" ``` ] ] --- # Automatização - publicação `.commit_and_push_website` .small[ ``` git add "${POST_RELATIVE_PATH}" git add "${POST_IMAGE_RELATIVE_PATH}" git commit -m "Publishing s01e01.md + s01e01.jpg" git push ``` ] --- # Automatização ## Github Actions .small[ ``` jobs: deploy: runs-on: ubuntu-20.04 steps: - name: Build run: | hugo --gc --minify --cleanDestinationDir [ -f ./CNAME ] && cp ./CNAME ./public/CNAME || true [ -f ./ALIAS ] && cp ./ALIAS ./public/ALIAS || true - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./public ``` ] --- # Automatização ## Github Actions (auto-publish) .small[ ``` on: schedule: # Every Friday at 1:00 (AM) UTC - cron: '0 1 * * 5' push: branches: - main ``` ] --- template: impact # That's all folks
--- # Para mais tarde ## Slides - https://tcarreira.github.io/presentations/marmita-de-redon/completo.html - https://github.com/tcarreira/presentations ## Conteúdos - https://marmita.pt - https://github.com/marmita-de-redon - site: https://github.com/marmita-de-redon/website - tema: https://github.com/marmita-de-redon/hugo-redon-podcast - automatização: https://github.com/marmita-de-redon/automation --- template: title
.content[.align-center[ ## Obrigado ]] .center.small[ tiago.carreira.pw | github.com/tcarreira | telegram: @tcarreira .tiny[ Autoria do Podcast: Joana Sanches, Marco Seabra, Tiago Carreira, Tiago MaurÃcio ] ]