ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Sunlapse] #1 촬영할 시간 구하기
    프로그래밍/프로젝트 2020. 12. 15. 20:43

    프로젝트를 위해 가장 먼저 할 것은 해가 뜨고 지는 시간을 구하는 것이었다. 일기예보도 있고 이 정도 API를 제공하는 곳은 분명 있지 않을까 싶었는데 역시 바로 찾을 수 있었다.

    https://sunrise-sunset.org/

     

    Sunset and sunrise times for any location - Free calendars and calculator

    Sunrise-Sunset is a free online tool that provides users information about day length, twilight, sunrise and sunset times for any location of the world. Our purpose is to make it easy to everybody to access Sun related information through simple tools that

    sunrise-sunset.org

    예상한 건 날씨 예보에 포함된 API 정도를 예상했는데 아예 일출, 일몰만 전문적으로 제공하는 API까지 있을 줄은 몰랐다. 예전에 써본 날씨 API와 달리 회원가입 등 귀찮은 절차도 필요하지 않았다. 집의 위도와 경도만 지도로 찾아서 구하고 넣으면 바로 확인 가능한 편리한 API이다.

    {
      "results":{
        "sunrise":"10:38:17 PM",
        "sunset":"8:16:33 AM",
        "solar_noon":"3:27:25 AM",
        "day_length":"09:38:16",
        "civil_twilight_begin":"10:09:23 PM",
        "civil_twilight_end":"8:45:27 AM",
        "nautical_twilight_begin":"9:36:51 PM",
        "nautical_twilight_end":"9:17:59 AM",
        "astronomical_twilight_begin":"9:05:13 PM",
        "astronomical_twilight_end":"9:49:36 AM"
      },
      "status":"OK"
    }

    다만 시간대가 UTC로 나와서 한 번 변환해줘야 하는 불편함이 있다. 한국은 UTC+9 시간대를 사용하니까 9시간을 더해준 시간을 사용하면 되는데 자연스럽게 sunrise, sunset의 시간대를 사용하려고 하는데 뭔가 어색했다. 일상의 기억과 비교했을 때 일출은 너무 늦은, 일몰은 너무 이른 시간이었던 것이다.

    찾아보니 일출과 일몰을 분리하는 개념이 있었다. 처음에 목표로 했던 완전히 어두운 새벽에서 완전히 어두운 저녁까지 영상을 촬영하려면 astronomical 기준으로 시간을 구해야 했다.

    import axios from "axios";
    import moment from "moment";
    
    const latitude = 37.561468;
    const longitude = 127.040485;
    
    export default async () => {
      const url = `https://api.sunrise-sunset.org/json?lat=${latitude}&lng=${longitude}`;
      const response = await axios.get(url);
    
      const sunriseTime = moment(
        response.data.results.nautical_twilight_begin,
        "hh:mm:ss a"
      )
        .subtract(1, 'day')
        .add(8, "hour");
    
      const sunsetTime = moment(
        response.data.results.astronomical_twilight_end,
        "hh:mm:ss a"
      )
        .add(8, "hour");
    
      const duration = moment.duration(sunsetTime.diff(sunriseTime));
    
      console.log('Sunrise: ' + sunriseTime.format('YYYY-MM-DD HH:mm:ss'));
      console.log('Sunset: ' + sunsetTime.format('YYYY-MM-DD HH:mm:ss'));
      console.log('Duration: ' + duration.asHours() + " hours");
    
      return {
        sunriseTime: getScheduleObj(sunriseTime),
        duration,
      };
    }
    
    function getScheduleObj(time) {
      return {
        year: time.year(),
        month: time.month(),
        date: time.date(),
        hour: time.hour(),
        minute: time.minute(),
        second: time.second(),
      };
    }
    

    API 요청에는 axios를 사용했다. 가능하면 바닐라 자바스크립트를 사용하는 것이 좋아서 보통은 fetch를 사용하지만 Node 환경에서는 fetch 역시 패키지 설치가 필요하기 때문에 차라리 좀더 편의 기능이 많고 요청 실패 처리 논리가 자연스러운 axios를 선택했다. 시간 처리에는 moment.js 라이브러리를 사용했다. 자바에서 Date 클래스를 쓰다가 LocalDate 클래스로 옮긴 것만큼이나 자바스크립트에서 시간 처리를 편하게 해주는 라이브러리다. 

     

    일출, 일몰 시간을 현지 시간으로 맞추기 위해 8시간을 더하고 너무 빡빡하게 찍지 않기 위해 일출은 5분을 빼주고 일몰은 5분을 더해줬다. 이 모듈에서는 sunriseTime 객체와 durationAsSeconds라는 숫자를 내놓는데 sunriseTime은 다음에 설명할 node-schedule 패키지가 원하는 객체 형태로 시간을 만든 것이고 durationAsSeconds는 영상 촬영에 사용할 FFmpeg의 명령어에 포함할 영상 촬영 시간을 초로 나타낸 숫자이다.

     

    다음에는 여기서 받은 시간을 이용해 FFmpeg의 실행을 node-schedule로 예약할 것이다.

     

     

    수정1: 실제로 촬영 후 초반의 어두운 시간이 너무 길어 앞뒤로 5분을 더해주고 빼주는 것을 없앴다. 천문박명(astronomical dawn)에서 항해박명(nautical dawn)으로 시작 시간도 수정했다.

    수정2: duration은 그대로 사용하는 것으로 변경했다. 이후에 테스트 후 수정을 거치다보니 초단위보다는 밀리초 단위로 사용하는 경우가 더 많았다.

Designed by Tistory.