1

How to create a movie from a .esp file (which is actually JSON) and a set of images that Google Earth Studio generates when you render?

The docs recommend Adobe products, but those are paid and I only need this once: https://earth.google.com/studio/docs/making-animations/rendering/

Alex
  • 2,953
  • 1
  • 27
  • 37

3 Answers3

3

You can use ffmpeg

Like so:

ffmpeg -f image2 -r 30 -i your_project%03d.png -c:v libx264 -pix_fmt yuv420p out.mp4

Where the -r flag is the Frame rate you chose, and the -i flag the name pattern of the jpges in the footage folder.

Alex
  • 2,953
  • 1
  • 27
  • 37
1

You can use Blender which is free. It already has a plugin that allows you to import the jpg sequence rendered in Google Earth Studio with the JSON file so that you can edit your video and use the track points.

0

I assume this question was about an older/outdated version of Earth Studio since, nowadays, you can simply choose to render as an .mp4.

Plus, there's even the option to render as a 360° spherical .mp4... very cool when played on an Oculus Quest - as long as I avoid including sudden turns in the animation. (I literally almost barfed, which was simultaneously awful and awesome.)

screamshot

On the other hand, the question says "movie" (without a filetype) which is pretty vague, so I'll paste in some [messy] JavaScript that I slapped together to dynamically display a set of rendered .jpeg frames, automatically progressing through the frames -- but with an <input type="range"> slider to also allow manual movement through the frames...

<style>
  body{ font-family:sans-serif; 
    background:#000; color:#fff; 
    margin:0; 
    overflow:hidden; }

  #cont{ position:absolute;
    width:min(1000px,98vw);
    height:min(1000px,98vh);
    left:50%; top:50%;
    transform:translate(-50%,-50%);}

  img{ max-width:100%; max-height:100%;
    position:absolute; left:50%; top:50%;
    transform:translate(-50%,-50%);}

  #rgcont{ position:absolute; z-index:99;
    left:3%; right:3%; top:3%; 
    width:100vw; height:20px; 
    transform-origin:3% 3%; 
    transition:300ms;}

  input{ width:90%; left:50%;
    transform:translatex(-50%); 
    position:absolute;
    filter: drop-shadow(3px 3px 5px #000)  
            drop-shadow(-3px -3px 5px #000); }

  @media(orientation:landscape){
    #rgcont{ width:100vh;
      transform:rotate(90deg) translatey(-50%); }
  }

  #info{ position:absolute; 
    right:5px; bottom:5px; 
    font-size:22px; }
</style>

&

<div id='cont'><img id='iimg' src=''></div>
<div id='rgcont'>
  <input type="range" id='rg' min='0' max='182' value='0' oninput="slid()">
</div>
<div id='info'></div>

<script>
  var imgs={}, loaded=0, 
      urls=[], auto=true, idx=0;

  for(var i=0;i<=182;i++){
    var n=i.toString().padStart(3,'0'),
    url="https://example.com/myframes_"+n+".jpeg"; 
    urls.push(url);
    imgs[i]=new Image(1000,1000);
    imgs[i].addEventListener('load',did1);
    imgs[i].src=url;
  }

  function did1(e){
    info.innerHTML=(100*((++loaded)/183)).toFixed()+'%';
     if(loaded==1){frame();}
  }
  function slid(){ 
    idx=parseInt(rg.value);
    auto=false;
   frame(idx); 
  }

  function frame(){
    iimg.src=urls[idx];
    if(auto){
      if((++idx)<=182){
        requestAnimationFrame(frame)
      }else{
        idx=182;
        auto=false;
      }
      rg.value=idx;
    }
  }
</script>

The hard-coded 182 is the total count of frames. Again, I'm not claiming this code works; just giving an idea.

ashleedawg
  • 20,365
  • 9
  • 72
  • 105