3D

David Walsh Blog

Crie uma imagem panorâmica 3D com um quadro-quadro

Nos cinco anos que estive na Mozilla, vi alguns projetos impressionantes. Alguns deles muito populares, alguns deles muito nicho, mas nenhum deles me inspirou a maneira como o trabalho da equipe MozVR com o WebVR e o projeto A-Frame .
Um quadro

A-Frame é um projeto comunitário com o objetivo de ser "blocos de construção para a web de realidade virtual", uma biblioteca para criar experiências VR no navegador usando marcação ou JavaScript. Saltar para usar um projeto como este pode ser irresistível, então vamos começar simples: criando uma demo de imagem panorâmica interativa como essa !

Tomando uma imagem em 3D

A maneira mais fácil de tirar uma imagem que satisfaça o requisito de efeito panorâmico (conhecido como formato equirectangular) é usando seu telefone. Guri VR de Dan Zajdband  : Realidade virtual para o resto de nós identifica aplicativos para iOS ( Google Street View ) e Android ( Photo Sphere ou Cardboard Camera ). O fantástico artigo de Dan também aponta um  grupo Equirectangular no Flickr se você preferir simplesmente pegar uma imagem existente para sua experimentação.
Tirar uma imagem de qualidade no seu telefone pode ser um pouco de desafio - você precisará de uma mão firme para evitar bordas irregulares enquanto gira o telefone para tirar imagens em cada posição.
Nota rápida: para a demonstração, estou usando a imagem de amostra fornecida pela A-Frame, porque a imagem do Google Street View gerou uma imagem de 10MB e isso seria uma besta para você. Se você quiser ver o que fiz usando o aplicativo GSV, você pode encontrar a imagem aqui . A imagem é tirada do ponto de vista de mim em pé no meio do beco sem saída em que vivo.

Criando o efeito panorâmico com um quadro A

Acredite ou não, tirar uma boa imagem é a parte mais difícil, porque o A-Frame torna a imagem em uma visualização 3D incrivelmente fácil. <a-sky> elemento dentro de A-Frame será usado para criar o efeito panorâmico:
< a-scene > 
  < a-sky  src = " https://davidwalsh.name/demo/3d-image.jpg "  rotation = " 0 -130 0 " > </ a-sky > 
</ a-scene >
O código acima é o uso declarativo (escrito em HTML) de A-Frame; você poderia usar JavaScript programático para criar o elemento em vez disso:
// Crie a cena 
var scene = document . createElement ( 'a-scene' ) ;

// Crie o céu 
var sky = documento . createElement ( 'a-sky' ) ; 
céu . src =  '3d-image.jpg' ; 
céu . setAttribute ( 'rotation' ,  { x :  0 , y :  - 130 , y :  0  } ) ;

// Injectar na 
cena da página . appendChild ( sky ) ; 
documento . corpo . appendChild ( cena ) ;
rotation atributo aceita separada por espaços xyz valores de rotação do eixo; Você pode jogar com aqueles para personalizar o posicionamento do ponto de vista.
A-Frame permite que você clique, segure e arraste o componente para girar em torno da imagem. Você também pode clicar na imagem de óculos VR para ver a imagem em 3D no seu telefone (o cartão é um acessório agradável!) Ou o navegador habilitado para WebVR.

A-Frame torna o 3D fácil!

Eu não estava exagerando quando disse que tirar a foto era a parte difícil; a quantidade de marcação necessária para criar um efeito panorâmico 3D é mínima quando você aproveita a força de A-Frame. Embora a criação de imagens panorâmicas seja um caso de uso popular, o efeito é apenas um uso simples do A-Frame. Quer ver o que mais A-Frame pode fazer? Confira as demonstrações no site da A-Frame  e aguardo com expectativa que veja mais sobre o WebVR em toda a web - é a próxima grande coisa!

Blog

Exemplos



Criar breve visualização do vídeo

A exibição de uma  imagem de visualização antes de carregar um vídeo é uma prática comum com a mídia da web nos dias de hoje; Muitas vezes, essa pré-visualização de imagem é o primeiro quadro do vídeo ou um quadro importante do vídeo. Se você visitou um site adulta recentemente (ahem), você notará que não só você obtém uma imagem de visualização, mas que paira sobre a referida imagem mostra um pequeno vídeo de amostra com trechos em diferentes pontos do filme. Naturalmente, eu estava interessado em como tudo isso funcionou e concluiu o seguinte:




  • Eles criam a imagem de visualização usando uma ferramenta como ffmpeg
  • Após o deslocamento da imagem, o vídeo de visualização é carregado de forma assíncrona em segundo plano
  • Uma vez que a imagem de visualização foi carregada, o vídeo é exibido sobre a imagem e reproduzido automaticamente
  • Quando o mouse sai, o vídeo está oculto (no caso de o usuário passar por cima da imagem novamente)

Alcançar o  swap <image><video>elemento é simples, mas eu queria saber como a PornHub, a maior rede de sites adulta, gerou seus vídeos de visualização. A idéia por trás do vídeo de visualização é simples, é claro, mas queria me ensinar mais sobre o ffmpeg e bash scripting. Aqui está a prova:


https://davidwalsh.name/demo/kung-fury-preview.mp4



Visualização de vídeo gerada a partir de um download local de Kung Fury .
Vamos desconstruir meu código para saber como esse vídeo de pré-visualização (muito básico) pode ser criado!

Executando o script






Nosso script, preview.shserá chamado da seguinte maneira:
# ./preview.sh {input.format} {output.format} 
$ ./preview.sh kung-fury.mp4 kung-fury-preview.mp4
Em um mundo perfeito, o script aceitaria lotes mais argumentos, como o tamanho de vídeo desejado ou qualquer uma das configurações que assumiremos dentro do script, mas eu queria me concentrar em obter a carne do script funcionando; A adição de argumentos de linha de comando seria um exercício rotineiro quando todo o resto era um ir.

O Script: preview.sh






O script começa com uma validação muito básica:
sourcefile = $ 1 
destfile = $ 2

# Validação excessivamente simples 
se  [  ! -e " $ sourcefile "  ] ;  em seguida, 
  echo  'Por favor, forneça um arquivo de entrada existente.' 
  exit 
fi

se  [  " $ destfile "  ==  ""  ] ;  echo então 
  'Forneça um nome de arquivo de pré-visualização de saída'. exit fi 
  
Em seguida, temos uma série de variáveis ​​relacionadas ao comprimento do vídeo, pontos desejados no vídeo para cortar visualizações, o tamanho do vídeo, etc.:
# Detectar extensão de 
extensão de arquivo de destino = $ { destfile # *.}

# Obter o comprimento do video em segundos 
length = $ ( ffprobe $ sourcefile   -show_format 2 > & 1 |  sed -n 's / duration = // p'  |  awk  '{print int ( $ 0 )}' )

# Inicie 20 segundos no vídeo para evitar a abertura de créditos (arbitrários) 
starttimeseconds = 20

# Mini-snippets terá 2 segundos de comprimento 
snippetlengthinseconds = 2

# Vamos apontar para 5 trechos espalhados pelo video 
desejado = 5

# Garanta que o vídeo seja longo o suficiente para até mesmo incomodar o 
minlength de visualização = $ (( $ snippetlengthinseconds * $ desiredsnippets ))

# Dimensões de vídeo (estes provavelmente podem ser argumentos de linha de comando) 
dimensões = 640: -1

# Diretório temporário e arquivo de texto onde vamos armazenar fragmentos 
# Estes serão limpos e removidos quando a imagem de visualização for gerada 
tempdir = snippets
listfile = list.txt
Se o vídeo for muito curto para gerar uma visualização, simplesmente fiança:
# Visualizar e verificar o comprimento video 
echo  'Duração do vídeo:'  $ length 
se  [  " $ length "" $ minlength "  ] 
então 
  echo  'Video é muito curto. Saindo. 
  exit 
fi
Em seguida, geramos uma série de vídeos "snippet" em tempos calculados dentro do vídeo, salvando esses vídeos de snippet em um diretório temporário:
# Loop e gerar fragmentos de vídeo 
mkdir  $ tempdir 
interval = $ (( $ length / $ desiredsnippets - $ starttimeseconds ))
 para i em  $ ( seq 1 $ desiredsnippets )
   fazer 
    # Formatar as segundas marcas em hh: mm: ss format 
    start = $ (( $ (( $ i * $ interval )) + $ starttimeseconds )) 
    formattedstart = $ ( printf "% 02d:% 02d:% 02d \ n"  $ (( $ start / 3600 )) $ (( $ Start % 3600 / 60 ))  $ (( $ start % 60 )) ) 
    echo  'Gerando visualização parte'  $ i  $ formattedstart 
    # Gerar o trecho no tempo calculado 
    ffmpeg -i $ sourcefile -vf escala = $ dimensões - predefinido rápido -qmin 1 -qmax 1 -ss $ formattedstart -t $ snippetlengthinseconds  $ tempdir / $ i . $ extension  & > / dev / null
 done
Nota: copiar e cortar vídeos com ffmpeg é difícil se você não é um codec e especialista em mídia, o que certamente não sou. Essas configurações básicas permitem que o trabalho seja feito, mas talvez não da maneira mais ideal. Por favor, comente abaixo se você conhece uma maneira de melhorar o desempenho ou a qualidade do vídeo.
O último passo é concatenar os vídeos do snippet no vídeo de visualização final:
# Concat videos 
echo  'Gerando o arquivo de visualização final'

# Gerar um arquivo de texto com um local de vídeo de snippet por linha 
# (https://trac.ffmpeg.org/wiki/Concatenate) 
para f em  $ tempdir / * ;  faça o  eco  "arquivo" $ f '"  >>  $ listfile ;  feito

# Concatenar os arquivos com base na lista gerada 
ffmpeg -f concat -safe 0 -i $ listfile -c copiar $ destfile  & > / dev / null

Echo  'Feito! Marque '  $ destfile  '! '

# Limpeza 
rm -rf $ tempdir  $ listfile
A concatenação de vídeo é fácil neste caso porque estamos concatenando trechos do mesmo vídeo original. A concatenação seria muito mais difícil se estivéssemos usando vídeos de diferentes taxas de quadros, tamanhos, etc.
O roteiro final em toda a sua glória:
sourcefile = $ 1 
destfile = $ 2

# Validação excessivamente simples 
se  [  ! -e " $ sourcefile "  ] ;  em seguida, 
  echo  'Por favor, forneça um arquivo de entrada existente.' 
  exit 
fi

se  [  " $ destfile "  ==  ""  ] ;  echo então 
  'Forneça um nome de arquivo de pré-visualização de saída'. exit fi 
  


# Detectar extensão de 
extensão de arquivo de destino = $ { destfile # *.}

# Obter o comprimento do video em segundos 
length = $ ( ffprobe $ sourcefile   -show_format 2 > & 1 |  sed -n 's / duration = // p'  |  awk  '{print int ( $ 0 )}' )

# Inicie 20 segundos no vídeo para evitar a abertura de créditos (arbitrários) 
starttimeseconds = 20

# Mini-snippets terá 2 segundos de comprimento 
snippetlengthinseconds = 2

# Vamos apontar para 5 trechos espalhados pelo video 
desejado = 5

# Garanta que o vídeo seja longo o suficiente para até mesmo incomodar o 
minlength de visualização = $ (( $ snippetlengthinseconds * $ desiredsnippets ))

# Dimensões de vídeo (estes provavelmente podem ser argumentos de linha de comando) 
dimensões = 640: -1

# Diretório temporário e arquivo de texto onde vamos armazenar fragmentos 
# Estes serão limpos e removidos quando a imagem de visualização for gerada 
tempdir = snippets
listfile = list.txt

# Visualizar e verificar o comprimento video 
echo  'Duração do vídeo:'  $ length 
se  [  " $ length "" $ minlength "  ] 
então 
  echo  'Video é muito curto. Saindo. 
  exit 
fi

# Loop e gerar fragmentos de vídeo 
mkdir  $ tempdir 
interval = $ (( $ length / $ desiredsnippets - $ starttimeseconds ))
 para i em  $ ( seq 1 $ desiredsnippets )
   fazer 
    # Formatar as segundas marcas em hh: mm: ss format 
    start = $ (( $ (( $ i * $ interval )) + $ starttimeseconds )) 
    formattedstart = $ ( printf "% 02d:% 02d:% 02d \ n"  $ (( $ start / 3600 )) $ (( $ Start % 3600 / 60 ))  $ (( $ start % 60 )) ) 
    echo  'Gerando visualização parte'  $ i  $ formattedstart 
    # Gerar o trecho no tempo calculado 
    ffmpeg -i $ sourcefile -vf escala = $ dimensões - predefinido rápido -qmin 1 -qmax 1 -ss $ formattedstart -t $ snippetlengthinseconds  $ tempdir / $ i . $ extension  & > / dev / null
 done

# Concat videos 
echo  'Gerando o arquivo de visualização final'

# Gerar um arquivo de texto com um local de vídeo de snippet por linha 
# (https://trac.ffmpeg.org/wiki/Concatenate) 
para f em  $ tempdir / * ;  faça o  eco  "arquivo" $ f '"  >>  $ listfile ;  feito

# Concatenar os arquivos com base na lista gerada 
ffmpeg -f concat -safe 0 -i $ listfile -c copiar $ destfile  & > / dev / null

Echo  'Feito! Marque '  $ destfile  '! '

# Limpeza 
rm -rf $ tempdir  $ listfile

Melhorias






Você pode apostar que o PornHub e todos os outros sites de vídeo que empregam esta técnica têm um script muito mais seguro e poderoso do que esse script. Algumas maneiras de melhorar esse script:
  • Validação:   Verifique se o arquivo existe, mas não há verificação para garantir que seja um arquivo de mídia válido.
  • Argumentos da linha de comando:  configurações como o tamanho do vídeo provavelmente devem ser um argumento de linha de comando opcional.
  • Codificação:   eu sei que argumentos de linha de comando adicionais precisam ser passados ​​dependendo do tipo de arquivo de vídeo (e há um bilhão lá fora). Um roteiro sério seria realmente de acordo com essa lógica.
  • Otimização:  nem estou perto de um vídeo ou especialista em mídia de qualquer tipo. Tem que haver uma maneira de acelerar o processo de geração de fragmentos, já que é bastante lento dentro do script agora. Eu costumo adicionar -c copy quando eu faço arquivos, mas ffmpeg gritou para mim, então eu passei nesse argumento. Por favor, compartilhe se você sabe como melhorar o processo de corte ou concatenação!
  • Dependências:   não necessariamente e melhorias, mas é importante chamar a atenção para o fato de que uma simples brew install ffmpeg não obterá muitos codecs e codificações que suportam suas necessidades. Eu precisava fazer o seguinte para trabalhar com o webm's, por exemplo:
    brew reinstale ffmpeg --with-fdk-aac --with-ffplay --with-freetype --with-frei0r --with-libass --with-libvo-aacenc --with-libvorbis --with-libvpx --with -opencore-amr --with-openjpeg --with-opus --with-rtmpdump --with-speex --with-theora --with-tools --with-libvorbis
Aproveitar o tempo para juntar esse script foi emocionante; uma mistura de manipulação de mídia, scripts bash e ver o produto final para algo que é usado em dezenas de sites de vídeo faz com que um real sentimento de conquista. Por favor, deixe-me saber como o script acima pode ser melhorado!




Nenhum comentário:

Postar um comentário