Bom dia, boa tarde, boa noite!
Essa é a décima e última parte da série sobre o projeto Video Creator, onde mostrarei como fiz o upload automático do video no o Youtube.
Se você entrou direto nesse post, te aconselho a começar por aqui, para entender exatamente do que se trata essa série.
Sobre essa parte
Para fazer o upload do video no Youtube, usei apenas algumas configurações básicas, mas vale muito a pena dar uma olhada na documentação da API, porque tem muita opção para configurar. Para esse projeto, segui o mais básico.
Requisitos:
Para essa parte, precisaremos habilitar a API do Youtube na sua conta Google Cloud, baixar o arquivo com a secret key que será gerada, fazer alguns imports e está quase tudo pronto. Isso porque 90% do código já está pronto no próprio site da API, e é ele que vamos usar como base:
https://developers.google.com/youtube/v3/guides/uploading_a_video#Sample_Code
Habilitar API do Youtube:
Visite o link abaixo e entre na sua conta, ou crie uma, é gratuíto é tão simples quando criar qualquer outra conta de serviço web.
Após logado, você precisará criar um novo projeto, ao lado de Google Cloud Platform, clique no menu dropdown e a modal abaixo aparecerá, clique em Novo Projeto, preencha com o nome desejado e clique em criar. Se o projeto não ficar selecionado automaticamente, clique novamente no menu dropdown e selecione o projeto recém criado.

Agora clique nas barrinhas horizontais no canto superior esquerdo da tela, depois vá em APIs e serviços, e por fim selecione Biblioteca.

Na tela que abrir, selecione Youtube Data Api v(x)
:

Na tela que abrir, clique no botão ativar, e sua tela ficará assim:

Para visitar a documentação da API, clique em TESTAR ESTA API.
Clique em Gerenciar
, e na tela que abrir, selecione a aba Credenciais
e depois em Criar credenciais
.

Selecione ID do cliente OAuth.
Em tipo de aplicativo, selecione Aplicativo da WEB:

Digite um nome, e depois em criar, aparecerá um modal com seu ID de cliente e Chave secreta de cliente. Você pode salvar esses dados em um arquivo de config, ou fazer como eu fiz, que é na listagem de credenciais, clicar no botão de download, e baixar o arquivo com esses dados.
Hora de codificar:
Com a API ativada e o arquivo com a secret key já salvo na pasta credentials, é hora de pegar o sample code e fazer algumas personalizações.
O robô inicia com a função start()
, que carrega o conteúdo do arquivo content.json para dentro do objeto video_content, cria o objeto youtube, e nesse momento, o navegador abrirá perguntando para qual conta do Youtube você deseja fazer o upload. Após isso, ele chama a função create_thumbnail()
, que cria as thumbnails e inicia o processo de Upload.
A função start() ficou assim:
def start():
logging.info('--- Starting Youtube robot ---')
video_content = rcontent.load()
youtube = get_authenticated_service()
try:
create_thumbnail(video_content)
initialize_upload(youtube, video_content)
result = "Upload concluído!"
except HttpError as e:
result = "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
except Exception as ex:
result = ex
print(result)
A função create_thumbnail() ficou assim:
def create_thumbnail(video_content):
logging.info("Creating Thumbnail...")
# apagando as thumbs existentes
os.system("rm -rf {}/thumb*".format(CONTENT_IMAGES_PATH))
# criando os comandos para execução.
# Importante: Refatorar para que a montagem do comando esteja dentro de um for
command_thumb_default = "convert -size {}x{} -font helvetica -pointsize 24 -background 'black' -fill white -gravity center caption:'{}' ./content/images/thumb_default.png"\
.format(YOUTUBE_VIDEO_THUMBNAILS['default']['width'],YOUTUBE_VIDEO_THUMBNAILS['default']['height'], video_content['youtube_details']['title'])
command_thumb_medium = "convert -size {}x{} -font helvetica -pointsize 26 -background 'black' -fill white -gravity center caption:'{}' ./content/images/thumb_medium.png"\
.format(YOUTUBE_VIDEO_THUMBNAILS['medium']['width'],YOUTUBE_VIDEO_THUMBNAILS['medium']['height'], video_content['youtube_details']['title'])
command_thumb_high = "convert -size {}x{} -font helvetica -pointsize 30 -background 'black' -fill white -gravity center caption:'{}' ./content/images/thumb_high.png"\
.format(YOUTUBE_VIDEO_THUMBNAILS['high']['width'],YOUTUBE_VIDEO_THUMBNAILS['high']['height'], video_content['youtube_details']['title'])
command_thumb_standard = "convert -size {}x{} -font helvetica -pointsize 50 -background 'black' -fill white -gravity center caption:'{}' ./content/images/thumb_standard.png"\
.format(YOUTUBE_VIDEO_THUMBNAILS['standard']['width'],YOUTUBE_VIDEO_THUMBNAILS['high']['height'], video_content['youtube_details']['title'])
command_thumb_maxres = "convert -size {}x{} -font helvetica -pointsize 70 -background 'black' -fill white -gravity center caption:'{}' ./content/images/thumb_maxres.png"\
.format(YOUTUBE_VIDEO_THUMBNAILS['maxres']['width'],YOUTUBE_VIDEO_THUMBNAILS['high']['height'], video_content['youtube_details']['title'])
os.system(command_thumb_default)
os.system(command_thumb_medium)
os.system(command_thumb_high)
os.system(command_thumb_standard)
os.system(command_thumb_maxres)
Uma informação importante, é que nessa função eu faço todas as possíveis thumbnails que o Youtube permite, porém não consegui fazer funcionar o upload das thumbnails junto com o video. Precisei utilizar a função set do objeto thumbnails após o upload de video.
Abaixo, as 2 funções que fazem o processo de upload do video:
def initialize_upload(youtube, video_content):
list_of_used_images = '\n'.join('✅ ' + img for img in video_content['images_used'])
list_of_sentences = '\n'.join([ s['text'] for s in video_content['sentences']])
YOUTUBE_VIDEO_DESCRIPTION = """
Conheça um pouco mais sobre {}:
{}
👉 Referências:
💥 Wikipedia
💥 Custom Search API - Bing.
👉 Imagens utilizadas no vídeo:
{}
""".format(video_content['search_term'], list_of_sentences, list_of_used_images)
YOUTUBE_VIDEO_FILE = CONTENT_PATH + '/{}'.format(video_content['video_filename'])
body= {
"snippet": {
"title": video_content['youtube_details']['title'],
"description": YOUTUBE_VIDEO_DESCRIPTION,
"tags": get_tags(video_content),
"categoryId": video_content['youtube_details']['category_id']
},
"status": {
"privacyStatus": YOUTUBE_VIDEO_PRIVACY_STATUS
}
}
# Call the API's videos.insert method to create and upload the video.
insert_request = youtube.videos().insert(
part=",".join(body.keys()),
body=body,
# The chunksize parameter specifies the size of each chunk of data, in
# bytes, that will be uploaded at a time. Set a higher value for
# reliable connections as fewer chunks lead to faster uploads. Set a lower
# value for better recovery on less reliable connections.
#
# Setting "chunksize" equal to -1 in the code below means that the entire
# file will be uploaded in a single HTTP request. (If the upload fails,
# it will still be retried where it left off.) This is usually a best
# practice, but if you're using Python older than 2.6 or if you're
# running on App Engine, you should set the chunksize to something like
# 1024 * 1024 (1 megabyte).
media_body=MediaFileUpload(YOUTUBE_VIDEO_FILE, chunksize=-1, resumable=True)
)
insert_response = resumable_upload(insert_request)
# set thumbnail
set_thumbnail(youtube, insert_response['id'])
# This method implements an exponential backoff strategy to resume a
# failed upload.
def resumable_upload(insert_request):
response = None
error = None
retry = 0
while response is None:
try:
print ("Uploading file...")
status, response = insert_request.next_chunk()
if response is not None:
if 'id' in response:
print ("Video id '%s' was successfully uploaded." % response['id'])
else:
exit("The upload failed with an unexpected response: %s" % response)
except HttpError as e:
if e.resp.status in RETRIABLE_STATUS_CODES:
error = "A retriable HTTP error %d occurred:\n%s" % (e.resp.status,e.content)
else:
raise
except RETRIABLE_EXCEPTIONS as e:
error = "A retriable error occurred: %s" % e
if error is not None:
print (error)
retry += 1
if retry > MAX_RETRIES:
exit("No longer attempting to retry.")
max_sleep = 2 ** retry
sleep_seconds = random.random() * max_sleep
print ("Sleeping %f seconds and then retrying..." % sleep_seconds)
time.sleep(sleep_seconds)
return response
Dentro da primeiro função initialize_upload(), comecei montando os dados que eu precisaria para fazer o upload do video, utilizei o assunto pesquisado, as sentenças e a lista de imagens usadas para compor a descrição do video e dar os devidos créditos para os sites detentores das imagens usadas.
Na hora de montar as tags, utilizei as keywords das sentenças para. Para isso, criei uma função para buscar as keywords e devolvê-las numa lista.
Ficou assim:
def get_tags(video_content):
keywords = []
for sentence in video_content['sentences']:
for k in sentence['keywords']:
if k not in keywords:
keywords.append(k)
return keywords
E após o upload, faço o set da thumbnail:
def set_thumbnail(youtube, video_id):
print('Setting the thumbnail: {} for video: {}'.format(CONTENT_IMAGES_PATH + "/thumb_maxres.png", video_id))
youtube.thumbnails().set(
videoId=video_id,
media_body=CONTENT_IMAGES_PATH + "/thumb_maxres.png"
).execute()
É isso!
Conclusão!
E assim encerro essa série de posts sobre o projeto Video-Creator. Muito feliz com o resultado final.
Sei que tem muitas coisas pra refatorar, pra evoluir, muitas oportunidades de novas implementações, mas o objetivo principal foi atingido: Receber um assunto e gerar um video para o Youtube automaticamente.
Espero que tenham gostado da série, qualquer dúvida, sugestão ou crítica, por favor entrem em contato. Se tiver algum assunto relacionado a essa série de posts que vocês queiram que eu me aprofunde um pouco mais na explicação, mandem um comentário pedindo, prometo trazer assim que possível.
Um grande abraço!