티스토리 뷰

개요

  • Vimeo는 전세계를 대상으로 하는 동영상 플랫폼이다. YouTube가 대중에게 공개된 동영상을 통해 광고 수입을 창출하는 플랫폼이라면, Vimeo는 동영상을 업로드하는 회원에게 과금하는 수익 구조를 가지고 있다. Vimeo는 개발자 친화적이라 제공되는 개발 가이드를 정독하고 따르면 어렵지 않게 동영상 업로더와 플레이어를 사이트에 결합할 수 있다.

과금 정책

  • Vimeo는 회원에 대한 월 단위 요금제를 제공하고 있다. 모든 요금제는 첫 30일 동안 무료 체험이 가능하며, 무제한 대역폭과 커스텀 플레이어를 제공하는 것이 특징이며, 업로드할 파일 크기와 동영상 길이에 대한 어떠한 제약도 없다. [요금제 안내 링크]
  • Basic 멤버십은 완전 무료로 총 5GB(주당 500MB 업로드 제한)의 저장소, 단일 사용자를 제공한다. API를 이용한 비디오 파일 제어를 지원하지 않는다.
  • Plus 멤버십은 월 7,350원으로 총 250GB(주당 5GB 업로드 제한)의 저장소, 단일 사용자를 제공한다. API를 이용한 비디오 파일 제어를 지원한다.
  • Pro 멤버십은 월 21,000원으로 총 1TB(주당 20GB 업로드 제한)의 저장소, 최대 4명 사용자를 제공한다. API를 이용한 비디오 파일 제어를 지원한다.
  • Business 멤버십은 월 51,840원으로 총 5TB(업로드 제한 없음)의 저장소, 최대 10명 사용자를 제공한다. API를 이용한 비디오 파일 제어를 지원한다.
  • Premium 멤버십은 월 78,000원으로 총 7TB(업로드 제한 없음)의 저장소, 최대 10명 사용자, 무제한 라이브 스트리밍을 제공한다.

앱의 생성

  • Vimeo의 멤버십에 가입한 후, 별도의 애플리케이션에서 자유롭게 Vimeo의 동영상 업로드 기능을 이용하려면 해당 애플리케이션을 App으로 등록하는 절차가 필요하다. 한 번 App을 생성하면 API를 호출하여 자유롭게 원하는 작업을 수행할 수 있다. 여기를 클릭하면 앱을 생성하는 페이지로 이동한다.
  • 앱 생성에 필요한 정보는 App NameApp Description 뿐이다. 입력 후 Create App을 클릭하면 앱이 생성된다. 앱 생성이 완료되면 client_idclient_secret을 알려주는 페이지로 이동한다. API 호출시 필요한 access_token를 생성할 수 있는 중요한 정보이므로 이 값을 잘 적어두도록 한다.
  • 또한, 앱을 생성하는 대부분의 목적은 동영상 업로드를 제어하기 위함이므로, Request Upload Access를 클릭하여 동영상 업로드 권한을 요청하도록 한다. Vimeo에서 리뷰 후 최종 승인하게 된다. 승인이 완료되면 upload 스코프를 사용할 수 있다.

동영상 업로드: HTML FORM 방식

  • 동영상 업로드는 Vimeo가 제공하는 업로드 페이지를 이용해도 되지만, 별도의 애플리케이션에서 동영상을 자유롭게 업로드를 이용하려면 API 가이드 문서를 따라 관련 코드를 제작하면 된다. [문서 링크]
  • 가장 익숙한 방법은 HTML FORM을 통해 Vimeo에 동영상을 업로드하는 것이다. 가장 먼저, 애플리케이션 서버 측에서는 매번 업로드 시점마다 아래 형식의 REST API를 호출하여 응답의 결과로 HTML FORM을 획득한다. 획득한 HTML FORM을 애플리케이션의 커스터마이징된 HTML 파일의 body 엘러먼트 내에 삽입하면 업로드에 필요한 준비가 완료된다.
$ curl -X POST \
  https://api.vimeo.com/me/videos \
  -H 'Authorization: bearer {access_token}' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/vnd.vimeo.*+json;version=3.4' \
  -d '{
  "upload": {
    "approach": "post",
    "redirect_url": "{redirect_url}"
  },
  "name": {name},
  "description": {description},
  "privacy": {
    "embed": "public",
    "view": "anybody"
  }
}'
  • redirect_url은 동영상 업로드의 성공 또는 실패 결과를 전달할 애플리케이션 서버 측의 리다이렉트 페이지 주소이다.
  • name은 업로드할 동영상 제목이고 description은 동영상 설명이다. 또한 privacy 항목을 통해 노출 정책을 입맛에 맞게 지정할 수 있다.
  • 요청이 유효할 경우, 201 Created 코드와 함께 아래 내용을 응답한다. link에서 동영상 주소를, embed.html에서 삽입 가능한 플레이어 HTML 플레이어를, 마지막으로 가장 중요한 upload.form에서 업로드 가능한 HTML FORM을 획득할 수 있다.
{
    "uri": "/videos/377186587",
    "name": "test",
    "description": "test_desc",
    "type": "video",
    "link": "https://vimeo.com/377186587",
    "duration": 0,
    "width": 400,
    "language": null,
    "height": 300,
    "embed": {
        "buttons": {
            "like": true,
            "watchlater": true,
            "share": true,
            "embed": true,
            "hd": false,
            "fullscreen": true,
            "scaling": true
        },
        "logos": {
            "vimeo": true,
            "custom": {
                "active": false,
                "link": null,
                "sticky": false
            }
        },
        "title": {
            "name": "user",
            "owner": "user",
            "portrait": "user"
        },
        "playbar": true,
        "volume": true,
        "speed": false,
        "color": "00adef",
        "uri": null,
        "html": "<iframe src=\"https://player.vimeo.com/video/377186587?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=161275\" width=\"400\" height=\"300\" frameborder=\"0\" allow=\"autoplay; fullscreen\" allowfullscreen title=\"test\"></iframe>",
        "badges": {
            "hdr": false,
            "live": {
                "streaming": false,
                "archived": false
            },
            "staff_pick": {
                "normal": false,
                "best_of_the_month": false,
                "best_of_the_year": false,
                "premiere": false
            },
            "vod": false,
            "weekend_challenge": false
        }
    },
    "created_time": "2019-12-03T23:16:41+00:00",
    "modified_time": "2019-12-03T23:16:41+00:00",
    "release_time": "2019-12-03T23:16:41+00:00",
    "content_rating": [
        "unrated"
    ],
    "license": null,
    "privacy": {
        "view": "anybody",
        "embed": "public",
        "download": true,
        "add": true,
        "comments": "anybody"
    },
    "pictures": {
        "uri": null,
        "active": false,
        "type": "default",
        "sizes": [
            {
                "width": 100,
                "height": 75,
                "link": "https://i.vimeocdn.com/video/default_100x75?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_100x75&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            },
            {
                "width": 200,
                "height": 150,
                "link": "https://i.vimeocdn.com/video/default_200x150?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_200x150&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            },
            {
                "width": 295,
                "height": 166,
                "link": "https://i.vimeocdn.com/video/default_295x166?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_295x166&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            },
            {
                "width": 640,
                "height": 360,
                "link": "https://i.vimeocdn.com/video/default_640x360?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_640x360&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            },
            {
                "width": 1280,
                "height": 720,
                "link": "https://i.vimeocdn.com/video/default_1280x720?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_1280x720&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            },
            {
                "width": 1920,
                "height": 1080,
                "link": "https://i.vimeocdn.com/video/default_1920x1080?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_1920x1080&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            },
            {
                "width": 640,
                "height": 480,
                "link": "https://i.vimeocdn.com/video/default_640x480?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_640x480&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            },
            {
                "width": 960,
                "height": 720,
                "link": "https://i.vimeocdn.com/video/default_960x720?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_960x720&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            },
            {
                "width": 1280,
                "height": 960,
                "link": "https://i.vimeocdn.com/video/default_1280x960?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_1280x960&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            },
            {
                "width": 1920,
                "height": 1440,
                "link": "https://i.vimeocdn.com/video/default_1920x1440?r=pad",
                "link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2Fdefault_1920x1440&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
            }
        ],
        "resource_key": "7a491d0e8cad256a8ac2fd6d207e647c1b034bad"
    },
    "tags": [],
    "stats": {
        "plays": 0
    },
    "categories": [],
    "metadata": {
        "connections": {
            "comments": {
                "uri": "/videos/377186587/comments",
                "options": [
                    "GET",
                    "POST"
                ],
                "total": 0
            },
            "credits": {
                "uri": "/videos/377186587/credits",
                "options": [
                    "GET",
                    "POST"
                ],
                "total": 1
            },
            "likes": {
                "uri": "/videos/377186587/likes",
                "options": [
                    "GET"
                ],
                "total": 0
            },
            "pictures": {
                "uri": "/videos/377186587/pictures",
                "options": [
                    "GET",
                    "POST"
                ],
                "total": 0
            },
            "texttracks": {
                "uri": "/videos/377186587/texttracks",
                "options": [
                    "GET",
                    "POST"
                ],
                "total": 0
            },
            "related": null,
            "recommendations": {
                "uri": "/videos/377186587/recommendations",
                "options": [
                    "GET"
                ]
            },
            "albums": {
                "uri": "/videos/377186587/albums",
                "options": [
                    "GET",
                    "PATCH"
                ],
                "total": 0
            },
            "available_albums": {
                "uri": "/videos/377186587/available_albums",
                "options": [
                    "GET"
                ],
                "total": 0
            },
            "available_channels": {
                "uri": "/videos/377186587/available_channels",
                "options": [
                    "GET"
                ],
                "total": 0
            }
        },
        "interactions": {
            "watchlater": {
                "uri": "/users/105836393/watchlater/377186587",
                "options": [
                    "GET",
                    "PUT",
                    "DELETE"
                ],
                "added": false,
                "added_time": null
            },
            "report": {
                "uri": "/videos/377186587/report",
                "options": [
                    "POST"
                ],
                "reason": [
                    "pornographic",
                    "harassment",
                    "advertisement",
                    "ripoff",
                    "incorrect rating",
                    "spam",
                    "causes harm"
                ]
            }
        }
    },
    "user": {
        "uri": "/users/105836393",
        "name": "json",
        "link": "https://vimeo.com/user105836393",
        "location": "",
        "bio": null,
        "short_bio": null,
        "created_time": "2019-12-03T02:27:49+00:00",
        "pictures": {
            "uri": null,
            "active": false,
            "type": "default",
            "sizes": [
                {
                    "width": 30,
                    "height": 30,
                    "link": "https://i.vimeocdn.com/portrait/defaults-blue_30x30.png"
                },
                {
                    "width": 75,
                    "height": 75,
                    "link": "https://i.vimeocdn.com/portrait/defaults-blue_75x75.png"
                },
                {
                    "width": 100,
                    "height": 100,
                    "link": "https://i.vimeocdn.com/portrait/defaults-blue_100x100.png"
                },
                {
                    "width": 300,
                    "height": 300,
                    "link": "https://i.vimeocdn.com/portrait/defaults-blue_300x300.png"
                },
                {
                    "width": 72,
                    "height": 72,
                    "link": "https://i.vimeocdn.com/portrait/defaults-blue_72x72.png"
                },
                {
                    "width": 144,
                    "height": 144,
                    "link": "https://i.vimeocdn.com/portrait/defaults-blue_144x144.png"
                },
                {
                    "width": 216,
                    "height": 216,
                    "link": "https://i.vimeocdn.com/portrait/defaults-blue_216x216.png"
                },
                {
                    "width": 288,
                    "height": 288,
                    "link": "https://i.vimeocdn.com/portrait/defaults-blue_288x288.png"
                },
                {
                    "width": 360,
                    "height": 360,
                    "link": "https://i.vimeocdn.com/portrait/defaults-blue_360x360.png"
                }
            ],
            "resource_key": "06cd312fcc3908e2d839aeb00ccaaf434acb0859"
        },
        "websites": [],
        "metadata": {
            "connections": {
                "albums": {
                    "uri": "/users/105836393/albums",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "appearances": {
                    "uri": "/users/105836393/appearances",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "categories": {
                    "uri": "/users/105836393/categories",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "channels": {
                    "uri": "/users/105836393/channels",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "feed": {
                    "uri": "/users/105836393/feed",
                    "options": [
                        "GET"
                    ]
                },
                "followers": {
                    "uri": "/users/105836393/followers",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "following": {
                    "uri": "/users/105836393/following",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "groups": {
                    "uri": "/users/105836393/groups",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "likes": {
                    "uri": "/users/105836393/likes",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "membership": {
                    "uri": "/users/105836393/membership/",
                    "options": [
                        "PATCH"
                    ]
                },
                "moderated_channels": {
                    "uri": "/users/105836393/channels?filter=moderated",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "portfolios": {
                    "uri": "/users/105836393/portfolios",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "videos": {
                    "uri": "/users/105836393/videos",
                    "options": [
                        "GET"
                    ],
                    "total": 3
                },
                "watchlater": {
                    "uri": "/users/105836393/watchlater",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "shared": {
                    "uri": "/users/105836393/shared/videos",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "pictures": {
                    "uri": "/users/105836393/pictures",
                    "options": [
                        "GET",
                        "POST"
                    ],
                    "total": 0
                },
                "watched_videos": {
                    "uri": "/me/watched/videos",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                },
                "folders": {
                    "uri": "/me/folders",
                    "options": [
                        "GET",
                        "POST"
                    ],
                    "total": 0
                },
                "block": {
                    "uri": "/me/block",
                    "options": [
                        "GET"
                    ],
                    "total": 0
                }
            }
        },
        "preferences": {
            "videos": {
                "privacy": {
                    "view": "anybody",
                    "comments": "anybody",
                    "embed": "public",
                    "download": true,
                    "add": true
                }
            }
        },
        "content_filter": [
            "language",
            "drugs",
            "violence",
            "nudity",
            "safe",
            "unrated"
        ],
        "upload_quota": {
            "space": {
                "free": 519650968,
                "max": 524288000,
                "used": 4637032,
                "showing": "periodic"
            },
            "periodic": {
                "free": 519650968,
                "max": 524288000,
                "used": 4637032,
                "reset_date": "2019-12-09 00:00:00"
            },
            "lifetime": {
                "free": 5364072088,
                "max": 5368709120,
                "used": 4637032
            }
        },
        "resource_key": "bbf5c82204cc66f9b28a76e69618e1be55750564",
        "account": "basic"
    },
    "review_page": {
        "active": true,
        "link": "https://vimeo.com/user105836393/review/377186587/5f9868ab4b"
    },
    "parent_folder": null,
    "last_user_action_event_date": "2019-12-03T23:16:41+00:00",
    "app": {
        "name": "api test app",
        "uri": "/apps/161275"
    },
    "status": "uploading",
    "resource_key": "162ec170048bcfb972fb43be4bff2655ad9f6f0f",
    "upload": {
        "status": "in_progress",
        "upload_link": "https://1512435597.cloud.vimeo.com/upload?ticket_id=276611150&video_file_id=1575222492&signature=852cb7186956b03fe8d0e1c67638eb63&v6=1&redirect_url=https%3A%2F%2Fvimeo.com%2Fupload%2Fapi%3Fvideo_file_id%3D1575222492%26app_id%3D161275%26ticket_id%3D276611150%26signature%3D7ef4559a25b0fe5f1a5ba65f034adb78ddb9eaae%26redirect%3Dhttp%253A%252F%252Flocalhost%253A8080",
        "form": "<form method=\"POST\" action=\"https://1512435597.cloud.vimeo.com/upload?ticket_id=276611150&video_file_id=1575222492&signature=852cb7186956b03fe8d0e1c67638eb63&v6=1&redirect_url=https%3A%2F%2Fvimeo.com%2Fupload%2Fapi%3Fvideo_file_id%3D1575222492%26app_id%3D161275%26ticket_id%3D276611150%26signature%3D7ef4559a25b0fe5f1a5ba65f034adb78ddb9eaae%26redirect%3Dhttp%253A%252F%252Flocalhost%253A8080\" enctype=\"multipart/form-data\">\n<label for=\"file\">File:</label>\n<input type=\"file\" name=\"file_data\" id=\"file\"><br>\n<input type=\"submit\" name=\"submit\" value=\"Submit\">\n</form>",
        "complete_uri": null,
        "approach": "post",
        "size": 4637032,
        "redirect_url": "http://localhost:8080",
        "link": null
    },
    "transcode": {
        "status": "in_progress"
    }
}
  • 업로드가 완료되면 {redirect_url}?video_uri=/videos/{video_id}와 같이 리다이렉트되어 애플리케이션 서버에서 업로드된 동영상의 ID를 획득할 수 있다.

동영상 업로드: tus 방식

  • tus 방식의 동영상 업로드는 Vimeo에서 가장 권장하는 방식으로, 동영상 업로드 중의 진행 경과를 실시간으로 확인할 수 있다는 장점이 있다. 구현에 앞서 tus 프로토콜에 대한 이해가 요구된다. 가장 먼저 애플리케이션 서버에서 아래와 같이 REST API를 호출하여 업로드 링크를 획득해야 한다.
$ curl -X POST \
  https://api.vimeo.com/me/videos \
  -H 'Authorization: bearer {access_token}' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/vnd.vimeo.*+json;version=3.4' \
  -d '{
  "upload": {
    "approach": "tus",
    "size": "{upload_file_size}"
  },
  "name": {name},
  "description": {description},
  "privacy": {
    "download"": "false",
    "embed": "public",
    "view": "anybody"
  }
}'
  • 업로드 링크가 생성되었다면, 애플리케이션 클라이언트에서는 해당 링크로 PATCH {upload.upload_link} 요청을 수행하면 실제 업로드가 시작된다. 각 애플리케이션의 개발 언어에 맞는 tus 프로토콜 라이브러리를 이용하면 편리하게 업로드를 구현할 수 있다.

동영상 업로드: 인터넷 주소 전달 방식

  • 인터넷 주소 전달 방식의 동영상 업로드는 기존에 이미 인터넷에 업로드되어 공개적으로 직접 다운로드 가능한 동영상의 URLVimeo에 전달하여 복제하는 방식이다. 업로드가 완료되면 201 코드를 응답한다.
$ curl -X POST \
  https://api.vimeo.com/me/videos \
  -H 'Authorization: bearer {access_token}' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/vnd.vimeo.*+json;version=3.4' \
  -d '{
  "upload": {
    "approach": "pull",
    "size": "{size}",
    "link": "{link}"
  },
  "name": {name},
  "description": {description},
  "privacy": {
    "download"": "false",
    "embed": "public",
    "view": "anybody"
  }
}'

동영상 업로드: 네이티브 iOS 모듈 방식

  • iOSVimeo가 공식으로 제작한 업로드 전용 SDK를 제공한다. [SDK 링크]

동영상 플레이어: 커스터마이징

  • Vimeo는 기본적으로 HTML5 플레이어를 제공한다. (동영상 업로드 후 응답에 포함된 embed.html 값에 해당한다.) Plus 이상의 유료 멤버십을 구독 중이라면, 동영상 플레이어의 외관을 자유롭게 커스터마이징할 수 있다. 설정 → 동영상 → 임베딩 사전 설정(또는 플레이어 로고) 메뉴에서 커스터마이징 설정이 가능하다. [관련 링크]
댓글
댓글쓰기 폼