Hi,
Estive dando uma olhada no sistema de identificação dos vídeos do YouTube e fiz um simples programa que retorna a URL de download para o respectivo vídeo.
Fiz o programa em duas linguagens: C e Perl.
Para usar o programa, basta abri-lo e fornecer a URL do vídeo, exemplo:
>> Digite o URL do video:
http://www.youtube.com/watch?v=xxxxxxx (http://www.youtube.com/watch?v=xxxxxxx)
Os vídeos do YouTube estão no formato .FLV (flash). Ao baixar o arquivo pela URL que o programa retornar, devemos realizar alguns procedimentos.
1) Pode-se obter um programa que execute tal formato, por exemplo o Riva FLV PLayer, que pode ser obtido em: http://baixaki.ig.com.br/site/detail36725.htm (http://baixaki.ig.com.br/site/detail36725.htm)
2) No Linux, pode-se converter o arquivo FLV para MPEG, permitindo que o vídeo seja executado em um player comum.
Para mais informações sobre a conversão:
http://br-linux.org/linux/node/4909 (http://br-linux.org/linux/node/4909)
Pois bem, primeiramente o código em C:
youtube.c
// Headers comuns
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32 // Se a plataforma for windows
#include <winsock.h> // Inclui header do winsock
WSADATA data; // WSADATA -> inicializar socket
SOCKET sock; // socket
#else //Caso contrário
// Headers para o uso de sockets no Linux
#include <unistd.h>
#include <sys/sockets.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
int sock; // socket
#endif
// Estruturas comuns -> configuração do socket e resolver DNS
struct sockaddr_in addr;
struct hostent * host = NULL;
#define YOUTUBE_IP "208.65.153.241" // IP do servidor
void encerra() // Função para fechar sockets
{
#ifdef WIN32 // Finaliza sockets no windows
closesocket(sock);
WSACleanup();
#else // Finaliza sockets no linux
close(sock);
#endif
}
void erro(const char * msg) // Mostra msg de erro e encerra
{
printf("%s",msg);
encerra();
exit(1);
}
void cria_sock(const char* IP) // Tenta criar socket e conectar no IP definido
{
if((sock = socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR) // Tenta criar socket
erro("Erro ao criar socket socket");
// Configura o socket para conectar na porta 80 do IP
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
addr.sin_addr.s_addr = inet_addr(IP);
// Tenta se conectar
if(connect(sock,(struct sockaddr*)&addr,sizeof(addr))==SOCKET_ERROR)
erro("Erro ao se conectar...");
}
int main()
{
// Limpa a tela
#ifdef WIN32
system("cls");
#else
system("clear");
#endif
puts(">> Digite a url do video: ");
char url[0x40]; // Obtém url do vídeo
fgets(url,0x40,stdin);
url[strlen(url)-1]='\0';
char * tok = strstr(url,"youtube.com/watch?v="); // Verifica validade da URL
if(tok == NULL)
erro("Url invalida!");
char video_id[0x20]; // Obtém ID do vídeo
snprintf(video_id,0x20,"%s",tok+20);
#ifdef WIN32 // Tenta inicializar winsock no windows
if(WSAStartup(0x101,&data)==-1)
erro("Erro ao inicializar Winsock.");
#endif
cria_sock(YOUTUBE_IP); // Tenta criar socket e conectar-se ao YouTube
int size = 50 + strlen(video_id);
char *req = (char*)malloc(size);
if(req == NULL)
erro("Erro ao alocar espaco..");
// Faz requisição HTTP para obter o vídeo
/*
GET watch?v=ID_DO_VIDEO HTTP/1.1
Host: www.youtube.com
*/
snprintf(req,size,"GET /watch?v=%s HTTP/1.1\r\nHost: www.youtube.com\r\n\r\n",video_id);
send(sock,req,strlen(req),0);
free(req);
puts("Procurando pelo video...");
tok = NULL; // Zera o ponteiro para utilizá-lo posterioremente no While Loop
char buffer[0x800]; // Buffer para receber dados
// Obtém headers
recv(sock,buffer,0x800,0);
// Verifica se houve um redirecionamento -> vídeo inválido
if(strstr(buffer,"HTTP/1.1 303")!= NULL)
erro("O video especificado parece nao existir.");
while(tok == NULL) // Recebe a resposta até que a URL do vídeo seja encontrada
{
memset(buffer,0x0,0x800); // Limpa o buffer
recv(sock,buffer,0x800,0);
tok = strstr(buffer,"player2.swf"); // Separa a URL do vídeo
}
closesocket(sock); // Fecha socket
cria_sock(YOUTUBE_IP); // Reconecta
tok = strtok(tok,"\""); // Tenta formatar a URL
if(tok == NULL)
erro("Erro ao obter URL do video...");
puts("Obtendo URL do video...");
char video_url[0x60];
snprintf(video_url,0x60,"%s",tok+12); // Escreve a URL formatada no buffer
size = 60 + strlen(video_url);
req = (char*)malloc(size);
if(req == NULL)
erro("Erro ao alocar espaco..");
/* Faz outra requisição:
GET /get_video?video_id=ID_DO_VIDEO&headers=.... HTTP/1.1
host: www.youtube.com
*/
snprintf(req,size,"GET /get_video?%s HTTP/1.1\r\nHost: www.youtube.com\r\n\r\n",video_url);
send(sock,req,strlen(req),0);
free(req);
int bytes = 1;
memset(buffer,0x0,0x800);
bytes = recv(sock,buffer,0x800,0); // Obtém headers
tok = strtok(strstr(buffer,"Location: "),"\r"); // Tenta obter URL de redirecionamento -> DOWNLOAD
if(tok == NULL)
erro("Erro ao obter URL de Download.");
memset(video_url,0x0,0x60);
snprintf(video_url,0x60,"%s",tok+10); // Escreve no buffer a URL
// Limpa a tela
#ifdef WIN32
system("cls");
#else
system("clear");
#endif
printf("Download do video:\n%s\n",video_url);
encerra(); // Finaliza
return 0;
}
Perl:
youtube.pl
use LWP::UserAgent; # Requisições HTTP
# Obtém URL do vídeo
print ">> Digite o URL do video:\n";
my $url = <stdin>;
chomp $url;
if(substr($url,0,7) ne "http://"){ # Inclui HTTP:// antes da url se necessário
$url = "http://$url";}
lc $url; # Conversão para minúsculas
if($url !~ /youtube.com\/watch\?v=/) # Verifica se a URL é válida
{
print "URL invalida!";
exit;
}
print "Procurando pelo video...\n";
my $useragent = LWP::UserAgent->new;
my $resp = $useragent->get($url); # Tenta obter o conteúdo da página
if($resp->is_error) # Em caso de erro
{
print "Ocorreu um erro ao fazer a requisicao.";
exit;
}
# Obtém a URL de onde o vídeo é exibido:
# www.youtube.com/player2.swf?URL_DO_VIDEO
# o programa irá obter apenas a URL_DO_VIDEO
# é necessário enviar uma requisição para www.youtube.com/get_video?URL_DO_VIDEO
my $redir = $resp->as_string;
$redir =~ m/player2.swf\?(.*?)\"/;
# Evita redirecionamento
sub LWP::UserAgent::redirect_ok { return 0;}
print "Obtendo URL de Download...\n";
# Formata a URL para fazer a requisição
$url = "http://www.youtube.com/get_video?$1";
my $useragent = LWP::UserAgent->new;
$resp = $useragent->head($url); # Tenta obter os headers
if($resp->is_error) # Em caso de erro
{
print "Erro ao obter URL de Download";
exit;
}
my $download = $resp->header("Location"); # Obtém o header de redirecionamento -> URL do vídeo
print "\nDownload do video:\n $download\n"; # Mostra o endereço
Por um problema de compatibilidade do meu modem com o Linux, não pude realizar testes no Linux. Se possível, gostaria que reportassem os possíveis erros lolz

Brigado hein...
Bye.
Hi,
Lolz... Me xingaram por ter feito os programas no modo console e até me ameacaram de morte hahuauha, zuando :)
Se vc pudesse comentar o codigo do vb seria de grande ajuda.
Dei uma olhada no projeto mas ja faz um tempim q nao mexia no vb,
com seus comentarios creio que seja de + facil o entendimento...
Flw
e aí blz :)
fiquei com uma duvida
o que essa linha faz
video_url = Mid(url.Text, InStr(1, url.Text, "youtube.com") + 11)
??
em C o equivalente seria essa parte ne?
snprintf(video_url,0x60,"%s",tok+12)
onde tok nesse caso (pelo q entendi seria a id do video)
e pq vc usa hexadecimais, humm, 0x20 seria 32 n eh?
huahuaa flw eh isso
po.. parabens

. Um programa de exelente utilidade. Tudo bem que ja existe um site que faz todo o servico.. keepmind.com algo assim, sei la. Bem, mesmo assim parabens.!
Ate mais.
Quote from: "dudeabot"e aí blz :)
fiquei com uma duvida
o que essa linha faz
video_url = Mid(url.Text, InStr(1, url.Text, "youtube.com") + 11)
??
em C o equivalente seria essa parte ne?
snprintf(video_url,0x60,"%s",tok+12)
onde tok nesse caso (pelo q entendi seria a id do video)
e pq vc usa hexadecimais, humm, 0x20 seria 32 n eh?
huahuaa flw eh isso :)
Hi,
Segue o código em VB, versão copy and paste, lolz:
' Função da API para executar comandos -> no programa: abrir URL
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Dim init As Boolean 'Validar -> conectar e obter url
Dim verif As Boolean ' Validar -> URL digitada
Dim redir As String ' URL de redirecionamento
Dim video_url As String 'URL do vídeo
Dim download_url As String 'URL para download
Dim data As String 'Buffer para receber dados do socket
Private Sub Form_Load()
' Estado inicial -> aguardando
init = True
verif = False
End Sub
Private Sub go_Click()
'Verifica se há dados digitados
If Len(url.Text) = 0 Then
MsgBox "Digite o endereço do Vídeo", vbCritical, "..."
Exit Sub
End If
'Verifica se a URL contém formatado válido
If InStr(1, url.Text, "youtube.com/watch?v=") = 0 Then
MsgBox "URL inválida!", vbCritical, "..."
Exit Sub
End If
'Tenta se conectar no youtube :)
sock.Connect "www.youtube.com", 80
Call disab 'Função -> disabilitar campos
End Sub
Private Sub sock_Connect() 'Ao conectar
Select Case init 'Verifica estado
Case True 'Se for a primeira conexão, diretamente em youtube.com
'Obtém URL de identificação do vídeo: "watch?v=XXXX"
video_url = Mid(url.Text, InStr(1, url.Text, "youtube.com") + 11)
'Envia requisição:
' GET URL_IDENTIFICAO HTTP/1.1
' host: www.youtube.com
'
sock.SendData "GET " + video_url + " HTTP/1.1" & vbCrLf & "Host: www.youtube.com" & vbCrLf & vbCrLf
Case Else 'Se não for primeira conexão -> obter URL de redirecionamento
'Envia outra requisição -> obter url de download:
' GET /get_video?REDIRECIONAMENTO HTTP/1.1
' host: www.youtube.com
sock.SendData "GET /get_video?" + redir + " HTTP/1.1" & vbCrLf & "Host: www.youtube.com" & vbCrLf & vbCrLf
End Select
End Sub
Private Sub sock_DataArrival(ByVal bytesTotal As Long) 'Ao receber resposta
'Recebe dados -> armazena no buffer "data"
sock.GetData data
Select Case init
Case True 'Se for a primeira conexão
If verificar = False Then 'Verifica se o vídeo foi encontrado -> Função
MsgBox "O video especificado para não existir!", vbExclamation, "..."
sock.Close 'Fecha o socket
Call hab 'Reabilita campos
Exit Sub 'Encerra
End If
'Verifca por "player2.swf?" na resposta da requisição.
'Exemplo: player2.swf?video_id=xxxxx&ssss=xxxx",...
If InStr(1, data, "player2.swf?") Then
redir = Mid(data, InStr(1, data, "player2.swf?") + 12) 'Retorna a string formada depois de "player2.swf?"
'Retorna a substring após "player2.swf?" retirando aspas "
'Ex: player2.swf?xxx=xxx&aaa=",... -> player2.swf?xxx=xxx&aaa=
redir = Mid(redir, 1, InStr(1, redir, Chr(34)) - 1)
init = False 'init = false -> na próxima conexão o programa irá executar as outras instruções abaixo
sock.Close 'Fecha socket
sock.Connect "www.youtube.com", 80 'Reconecta-se
End If
Case Else 'Se não for a primeira conexão
sock.Close 'Certifica-se que o socket foi fechado
'Obtém URL de download do header: "Location: URL_REDIR" -> "URL_REDIR"
download_url = Mid(data, InStr(1, data, "Location: ") + 10)
'Retira quebra de linha
download_url = Mid(download_url, 1, InStr(1, download_url, vbCrLf))
MsgBox "Pronto para download... Pressione OK para continuar...", vbInformation, "lolz"
'Abre a URL obtida no navegador
ShellExecute 0, "open", download_url, 0, 0, 0
Call hab 'Reabilita campos
init = True 'Como a segunda conexão foi feita com sucesso, para que se possa obter outros vídeos -> init=true -> primeiras instruções novamente
Exit Sub 'Encerra
End Select
End Sub
Private Sub sock_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
'Erro
MsgBox "Erro ao se conectar!", vbCritical, "..."
sock.Close 'Fecha socket
'Volta ao estado inicial
init = True
verif = False
Call hab 'Reabilita campos
End Sub
Sub hab() 'Torna habilitados: TextBox e o botão OK
url.Enabled = True
go.Enabled = True
End Sub
Sub disab() 'Torna disabilitados: TextBox e o botão OK
url.Enabled = False
go.Enabled = False
End Sub
Function verificar() As Boolean
If verif = True Then verificar = True 'Se já ouve a verificação encerra
If InStr(1, data, "HTTP/1.1 303") Then 'Verifica se foi retornado o código 303 -> redirecionamento
'Redirecionamento = vídoe não encontrado
verificar = False 'Retorna false -> vídeo não encontrado
Else
verificar = True 'Se não houver código 303 -> vídeo encontrado
verif = True 'Define que já houve a verificação
End If
End Function
no código C não tá faltando uma função para ele baixar o video n? pq parece q ele so vai ate o ponto de pegar a url
vlw
Hi,
Lolz, é porque quando eu escrevi o código, eu ainda não tive a idéia de fazer com que o download iniciasse automaticamente. A idéia surgiu quando estava escrevendo o código no Visual Basic.
Pode-se entretanto, adicionar a seguinte linha:
...
#ifdef WIN32 // Para windows
size = strlen(video_url) + 7;
char cmd[size];
snprintf(cmd,size,"start %s",video_url); // Executa comando: start URL_VIDEO -> abre navegador
system("cmd");
#else // Linux
size = strlen(video_url) + 6;
char cmd[size];
snprintf(cmd,size,"wget %s",video_url); // comando wget URL -> baixa o vídeo
system("cmd");
#endif
Bye
Hi,
pff, nem posso editar

O correto seria: system(cmd) e não system("cmd"); =\
Bye...
Testei no GNU/Linux

(//http://img211.imageshack.us/img211/8150/darkix7.jpg)
// insanity
eita já virou .pl? lol
para acessar o IE (q eh padrao no win32)
char teste[100];
sprintf(teste,"IEXPLORE %s", url_video);
cmd(teste);
t+
Quote from: "dudeabot"eita já virou .pl? lol
para acessar o IE (q eh padrao no win32)
char teste[100];
sprintf(teste,"IEXPLORE %s", url_video);
cmd(teste);
t+
ops, C não é java

sprintf(teste,"C:/Arquiv~1/Intern~1/IEXPLORE.EXE %s", "google.com");
system(teste);
agora sim..
Aqui o arquivo em Perl (.pl) deu alguns erros.

Linha 3 e 7.
https://addons.mozilla.org/search.php?q ... pp=firefox (https://addons.mozilla.org/search.php?q=youtube&app=firefox)
ai tem troço pra baxa vids do googlevid e youtube e mais uns ^^