반응형

구글 플레이스토어에 앱을 배포하는 과정은 크게 6단계로 나눌 수 있습니다. 각 단계를 차근차근 안내드리겠습니다.


1. Google Play 개발자 계정 등록

  • 개발자 계정 만들기: Google Play Console에서 개발자 계정을 등록합니다.
  • 수수료: 개발자 계정 등록 비용은 **25달러(한 번만 결제)**입니다.
  • 요구사항: Google 계정이 필요하며, 신용카드 또는 결제 수단을 사용해야 합니다.

2. 앱 준비

  • 앱 APK/AAB 파일 만들기
    • AAB (Android App Bundle): 구글 플레이는 AAB 파일을 권장합니다. AAB는 APK보다 최적화된 형태입니다.
    • Android Studio에서 앱을 빌드해 .aab 또는 .apk 파일을 생성합니다.
  • 앱 아이콘 및 그래픽 준비
    • 앱 아이콘: 512x512 픽셀, PNG 포맷
    • 스크린샷: 다양한 화면 크기별 스크린샷을 준비합니다 (예: 5~8장).
    • 앱 홍보 이미지: 선택 사항으로 1024x500 크기의 홍보 이미지를 준비합니다.
  • 앱 서명
    • 앱에 서명 키를 설정하고, 반드시 서명된 파일을 준비해야 합니다. App Signing by Google Play를 활용할 수도 있습니다.

3. Google Play Console에 앱 등록

  1. Google Play Console에 로그인합니다.
  2. 새 앱 만들기:
    • 앱 이름: 사용자가 볼 수 있는 앱 이름을 입력합니다.
    • 앱 언어: 기본 언어를 선택합니다 (예: 한국어).
    • 앱 유형: 앱(App)인지 게임(Game)인지 선택합니다.
    • 유료/무료: 앱이 무료인지 유료인지 선택합니다.
  3. 스토어 설정:
    • 앱 설명: 앱의 간단한 설명과 상세 설명을 작성합니다.
    • 앱 카테고리: 적절한 카테고리를 선택합니다.
    • 연락처 정보: 이메일 주소와 웹사이트, 연락처를 추가합니다.
    • 콘텐츠 등급 설정: 연령 적합성을 평가하는 콘텐츠 등급 질문지를 작성합니다.

4. 앱 배포를 위한 설정

  • 앱 버전 업로드:
    • AAB 파일 업로드: “릴리스 관리” > “프로덕션”에서 앱 파일을 업로드합니다.
    • 버전 코드와 버전 이름이 필요합니다.
  • 테스트:
    • 내부 테스트: 소규모 테스트 팀과 먼저 앱을 테스트할 수 있습니다.
    • 오픈 베타: 더 많은 사용자들에게 앱을 테스트할 기회를 제공합니다.
  • 정책 준수 및 개인정보처리방침 링크:
    • 앱이 구글의 정책을 위반하지 않도록 검토하고, 개인정보 처리방침 페이지를 준비합니다.

5. 앱 검토 및 배포

  1. 앱 검토 요청: 모든 설정이 완료되면 검토를 요청합니다.
  2. 검토 기간:
    • 앱 검토는 보통 몇 시간~3일 정도 소요됩니다.
    • 정책 위반 사항이 없으면 앱이 승인됩니다.

6. 앱 출시

  • 앱 게시: 검토가 완료되면 앱을 구글 플레이스토어에 게시할 수 있습니다.
  • 모니터링: Google Play Console에서 앱 다운로드 수, 사용자 리뷰, 오류 리포트를 확인하고 대응합니다.

추가 팁

  1. ASO (App Store Optimization)
    • 앱 이름과 설명에 검색 키워드를 포함하여 검색 노출을 높입니다.
  2. 리뷰 관리
    • 사용자 리뷰에 적극적으로 응답해 앱의 평점을 유지합니다.
  3. 업데이트
    • 정기적으로 기능 추가 및 오류 수정 업데이트를 진행합니다.
반응형
반응형

blob: URL은 웹 브라우저 내에서 파일 데이터를 임시로 다룰 수 있게 해주는 URL입니다. 이 URL은 다운로드하거나 다른 위치에서 접근할 수 있는 일반적인 URL이 아닙니다.

 

 

인스타로 개발자도구 열면

어떤건 src 링크따서 사진 다운 가능

어떤건 src 링크 따라가면 안나옴

 

blob:URL은 원본URL링크를 따야됨

어떻게?

 

 

반응형
반응형
인스타 동영상 다운로드하는 어플 만드는 법 알려줘
 
ChatGPT

인스타그램 동영상 다운로드 어플을 만드는 방법은 여러 가지가 있습니다. 여기서는 Python을 사용하여 간단한 인스타그램 동영상 다운로드 어플을 만드는 방법을 설명하겠습니다. 이 예제에서는 Python의 requests 라이브러리와 beautifulsoup4 라이브러리를 사용하여 웹 페이지를 스크랩하고, 동영상 URL을 추출하여 다운로드합니다.

  1. 필수 라이브러리 설치:
  2. bash
    코드 복사
    pip install requests beautifulsoup4
  3. 인스타그램 동영상 다운로드 스크립트 작성:
  4. python
    코드 복사
    import requests from bs4 import BeautifulSoup import re def download_instagram_video(url): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } response = requests.get(url, headers=headers) if response.status_code == 200: soup = BeautifulSoup(response.content, 'html.parser') scripts = soup.find_all('script', type='text/javascript') for script in scripts: if 'window._sharedData' in script.text: shared_data = script.text.split(' = ', 1)[1].rstrip(';') video_url = re.search(r'"video_url":"([^"]+)"', shared_data) if video_url: video_url = video_url.group(1).replace('\\u0026', '&') video_response = requests.get(video_url) with open('instagram_video.mp4', 'wb') as file: file.write(video_response.content) print("동영상 다운로드 완료!") return print("동영상을 찾을 수 없습니다.") else: print(f"페이지를 불러오는데 실패했습니다. 상태 코드: {response.status_code}") # 인스타그램 동영상 URL을 여기에 입력하세요 instagram_url = 'https://www.instagram.com/p/xxxxx/' download_instagram_video(instagram_url)
  5. 스크립트 실행:
    • 위의 스크립트에서 instagram_url 변수를 인스타그램 동영상 URL로 바꾸고 스크립트를 실행합니다.
    • 스크립트는 지정한 URL에서 동영상을 찾아 instagram_video.mp4 파일로 다운로드합니다.

주의사항:

  • 인스타그램의 서비스 이용 약관을 준수해야 합니다.
  • 이 스크립트는 교육 목적으로 제공되며, 실제 사용 시 관련 법률을 준수해야 합니다.
  • 인스타그램의 구조가 변경될 경우 스크립트가 동작하지 않을 수 있습니다.

어플 제작: 만약 이 기능을 앱으로 제작하고 싶다면, 다음 단계가 필요합니다:

  1. 프론트엔드 개발: 사용자가 URL을 입력할 수 있는 인터페이스 제작.
  2. 백엔드 개발: 위의 파이썬 스크립트를 서버에서 실행하여 동영상을 다운로드하고 사용자에게 제공.
  3. 배포 및 유지보수: 서버 배포와 지속적인 유지보수.

예를 들어 Flask 또는 Django 같은 웹 프레임워크를 사용하여 웹 앱으로 구현할 수 있습니다. 모바일 앱의 경우, React Native 또는 Flutter를 사용하여 구현할 수 있습니다.

반응형
반응형

https://medium.com/@kevinmenesesgonzalez/downloading-and-managing-youtube-audio-with-python-a-step-by-step-guide-2f1027227e2e#id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6ImYyZTExOTg2MjgyZGU5M2YyN2IyNjRmZDJhNGRlMTkyOTkzZGNiOGMiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiIyMTYyOTYwMzU4MzQtazFrNnFlMDYwczJ0cDJhMmphbTRsamRjbXMwMHN0dGcuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiIyMTYyOTYwMzU4MzQtazFrNnFlMDYwczJ0cDJhMmphbTRsamRjbXMwMHN0dGcuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDQwODIzNDY2NDc5MTEwNDk0MDAiLCJlbWFpbCI6ImNodXJsdW5nQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYmYiOjE3MjE2NTM3MTQsIm5hbWUiOiLroIjsmKTsgqzsnpAiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDMuZ29vZ2xldXNlcmNvbnRlbnQuY29tL2EvQUNnOG9jTENya2FrMFBWQnhWOGR1S1lQYi11X3dEYVlvbVZZdUZ2VFhYaFN0Z1QzTG11TG53PXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IuyCrOyekCIsImZhbWlseV9uYW1lIjoi66CI7JikIiwiaWF0IjoxNzIxNjU0MDE0LCJleHAiOjE3MjE2NTc2MTQsImp0aSI6Ijk0ZTI2YTUzOWVkOTYyMmEzOWNiNjNhYWYyMWI4Y2ZhYjE2ZDQ5ODEifQ.VZon9tyjtt-AkjDMW9kck-nk80YlrXHZ0kFxHTngV9zjn850vAMVH5MoI9LH7ShPJz6QejmsLPDdRhE80XhUnDXPxYUwIU5wjyMgcL_vTAyS0CWUgpk8rDBGNr92nQY8eTcTifU9yY2MDQd1ceen2h-6neVtKh-BxJYXf-WSxOacLisTkpzfM8F8l16rgwZHpwz1ycsPziBpd-TJpt8RUXEBfhUyEEjKqMofr7LjGm-0hEosUbRljdE89D7qCGVzAO3rVPMnAhKlMEemHnrIVUdrsedgVbSL26xJ28fo8IwCl8hvoPPQXSsZt8zXm32NWxQPqY2lmGLF6qDbgcafrA

반응형
반응형

https://bebutae.tistory.com/17

반응형
반응형

https://m.blog.naver.com/samsjang/220546649052

반응형
반응형

https://namu.wiki/w/youtube-dl

반응형
반응형

https://wiki.changwoo.pe.kr/project:youtubedownload

 

project:youtubedownload [ChangwooWiki]

파이썬을 이용한 유튜브 동영상 다운로드 유튜브를 모르시는 분들은 없겠죠? 이번에는 파이썬을 이용해 유튜브 동영상을 다운로드 받는 방법에 대해 적어 보겠습니다. 유튜브는 동영상을 스트

wiki.changwoo.pe.kr

 

파이썬을 이용한 유튜브 동영상 다운로드

유튜브를 모르시는 분들은 없겠죠? 이번에는 파이썬을 이용해 유튜브 동영상을 다운로드 받는 방법에 대해 적어 보겠습니다. 유튜브는 동영상을 스트리밍할 뿐, 따로 영상을 저장하는 기능은 제공하고 있지 않습니다. 그러나 유튜브의 동영상을 저장해 오프라인일 때에도 저장하고 싶다는 요구가 많이 있었죠. 그에 따라 유튜브의 영상을 어떻게든 추출해서 따로 저장하는 소프트웨어들이 정말 많이 나왔습니다. 운영체제에서 따로 돌아가는 응용 프로그램 형태로도, 웹브라우저의 확장 기능으로, 전용 웹서비스로, 쉘 스크립트로도, 또 모바일 앱 프로그램으로도요. 그래서 원하신다면 입맛에 맞는 유튜브 다운로드 프로그램을 이용하시면 매우 편리하게 영상을 다운로드 받을 수 있습니다.

그렇지만 어떻게 이런 프로그램들이 유튜브 동영상을 다운로드 받는지, 그리고 왜 유튜브는 그런 동영상을 다운로드 받는 것을 허용할 수 밖에 없는지에 대해 궁금증을 가져보신 적이 있으신지요? 저는 궁금했습니다. 그래서 (재미로) 한 번 해 보고, 이런 문서를 작성한 것입니다.

왜 막지 않을까?

유튜브가 동영상을 퍼가는 것을 제공하진 않지만, 굳이 막지는 않는 이유를 생각해 보았습니다. 이것은 제 생각을 적어 본 것이므로 사실과는 다를 수 있습니다.

유튜브도 HTTP Live Streaming을 합니다. 즉 동영상의 스트리밍이 웹페이지 파일 다운로드와 동일한 원리로 동작합니다. HTTP 프로토콜 설계 방식 상, 궁극적인 동영상의 추출 행위 차단은 매우 어렵습니다. 서버는 클라이언트에게 단순히 데이터를 제공하는 역할만을 하지, 그 이외의 것에 대해서는 별 관심 없습니다. 또 서버는 클라이언트가 왜 동영상을 받아가는지 알려고 하지 않습니다. 그리고 받아간 자료를 어떻게 사용할지도 알 수 없습니다.
이를 변경하려 하는 것은 HTTP 프로토콜 설계 근본을 건드리는 것과 같습니다. 그러므로 클라이언트의 의도와 동작을 서버가 강제하려고 들기 시작하면 일이 무진장 피곤해지고, 부작용도 일파만파 번지겠죠. 그럴 바에는 HTTP 기반의 스트리밍을 포기하는 것이 나을 지도 모릅니다. 그러나 그러기엔 HTTP 기반 스트리밍의 장점이 더 컸기에 사용하였겠죠. 기술적인 이유 이외에 여러 이유가 분명히 있겠지만, 제가 유튜브의 관계자가 아니므로 그런 것까지는 다 다룰 순 없겠군요.

다시 말하자면 유튜브 서버는 설계상 1회 감상을 위한 다운로드와 영구 저장을 위한 다운로드를 구분하는 것이 거의 불가능하며, 따라서 다운로드 받는 사용자의 의도를 일일이 구분하여 통제하는 것 또한 거의 불가능합니다. 또한 두 행위 자체가 기술적으로 별 차이점이 없습니다.

제 상식으로는 오프라인을 위해 개인적으로 영상을 다운로드 받아 따로 저장하는 것은 큰 문제가 없는 것으로 알고 있습니다. 하지만 저작권이 걸린 동영상을 법이 지정한 범위 밖으로 함부로 이용할 경우만 문제가 됩니다(그리고 이건 정말 만의 하나지만, 대한민국이 아닌 어떤 곳에서는 그런 행위 자체를 문제삼을 수 있을지도 모릅니다). 칼이 요리를 할 때 쓰이면 유용한 도구지만, 흉악한 범죄에 이용되면 흉기가 되는 것과 같은 이치입니다. 사용하는 사람이 올바른 지식과 적합한 의도를 갖고 사용해야 합니다.

그럼 어떻게 할까?

Firefox로 탐색해보기

저는 이럴 때 Firefox의 'HTTPFox' 부가 기능과 '문서 검사' 기능을 애용합니다. HttpFox는 Firefox의 모든 통신 내역을 아주 자세하게 보여줍니다. 그러므로 겉으로 보이지 않는 숨은 동작도 쉽게 파악할 수 있습니다. 그러면 아무 유튜브 동영상을 선택해, HttpFox를 동작시킨 상태에서 재생하도록 해 보겠습니다.

위 그림은 웹브라우저가 유튜브의 동영상 웹 페이지에 접근한 내역을 찾아 하이라이트시킨 것입니다. 확실히 text/html 문서로 응답을 받았습니다. 웹브라우저는 이제 이 문서를 파싱하여 문서가 요구하는 자바스크립트, 그림 등을 서버에서 받아 올 것입니다.

웹브라우저가 받아오는 여러 리소스(항목) 중에는 아래 그림과 같은 항목도 발견할 수 있을 것입니다. 이것은 동영상 파일임을 쉽게 눈치챌 수 있습니다. 이 파일을 읽어들여 웹 페이지의 플래시 플레이어가 비디오를 재생하는 것입니다. 보다 이 항목을 쉽게 발견하려면 동영상의 화질을 하나 선택해 고정하는 것이 좋습니다. 이유는 HTTP Live Streaming 문서를 보면 알 수 있을 것입니다.

비디오 재생을 잠시 멈추고 HttpFox에 있는 비디오 주소를 바로 복사해 Firefox 탭을 하나 열어 붙여 넣기를 합니다. 그러면…

이렇게 비디오가 받아집니다. 만일 지금 서버가 플래시 플레이어에서 재생할 목적으로 받는 것이 아님을 안다면, 그리고 그것을 강제할 의도라면 이런 일은 일어나지 않겠죠. 그러나 서버는 다행히도(?) 이를 구분할 방법이 없어 보입니다. 지금 이 결과를 보면 이렇게 생각할 수 있습니다.

유튜브 서버와 웹브라우저는 별다른 숨김이나 꼼수 없이, HTML 및 관련 기술만으로 동영상을 재생합니다(플래시 플러그인이 별도로 사용된 건 예외입니다). 한편 HttpFox는 동영상의 명시적인 주소를 붙잡았습니다. 그렇다면 이 명시적인 주소는 HTML 소스를 잘 분석하면 분명 금방 알아낼 수 있을 것입니다. 그러니까 모든 수수께끼의 답은 애초에 이미 HTML 소스가 가지고 있는 셈입니다. 사실 당연한 소리입니다. 무언가 저절로 하늘에서 뚝 떨어질 리 없지요 

 우리는 이를 차근차근 해석해 내기만 하면 됩니다. 이제 파이어폭스의 '문서 검사' 기능이 활약할 시간입니다.

문서 검사를 활성화하고 유튜브의 재생 화면을 클릭해 유튜브의 재생기가 HTML의 어떤 요소인지를 알아봅니다. 'movie_player'라는 id를 가진 embed 태그가 재생 화면을 담당하고 있음을 쉽게 알 수 있습니다. 그리고 이 태그의 flashvars 라는 속성에 매우 길게 무엇인가가 줄줄 적힌 것을 볼 수 있습니다.

보통 embded 태그는 웹페이지에 플래시 등의 플러그인을 삽입하기 위해 많이 사용합니다. 그리고 Adobe의 도움말에 따르면 embed 태그에서 플래시에 여러 정보를 전달하기 위해 flashvars 속성을 사용한다고 적혀 있습니다. 무언가 알아낸 느낌입니다!

자바스크립트 코드 해석하기

다만 여기서 조심해야 할 사항이 있습니다. Firefox의 문서 검사에 나오는 HTML 문서는 서버가 Firefox로 보낸 원본 HTML 코드가 아닌, 파이어폭스가 이해한 바를 바탕으로 재구성한 HTML 문서라는 점입니다. 그러므로 반드시 원본 대조(?)를 통해 정말 flashvars 속성이 소스에 있는지 확인해아 합니다. 이건 어려운 일이 아닙니다. '소스 보기'로 소스를 열어 봅니다. 그리고 'movie_player'나 'flashvars'라는 키워드로 embed 태그 부분을 살펴보기로 하지요.

<div id="watch7-player" class="flash-player"></div>
<script>
      (function() {
        var encoded = [];
        for (var key in yt.playerConfig.args) {
          encoded.push(encodeURIComponent(key) + '=' + encodeURIComponent(yt.playerConfig.args[key]));
        }
        var swf = "      \u003cembed type=\"application\/x-shockwave-flash\"     s\u0072c=\"http:\/\/s.ytimg.com\/yts\/swfbin\/watch_as3-vflXPuwnw.swf\"     id=\"movie_player\"    flashvars=\"__flashvars__\"     allowscriptaccess=\"always\" allowfullscreen=\"true\" bgcolor=\"#000000\"\u003e\n  \u003cnoembed\u003e\u003cdiv class=\"yt-alert yt-alert-default yt-alert-error  yt-alert-player\"\u003e  \u003cdiv class=\"yt-alert-icon\"\u003e\n    \u003cimg s\u0072c=\"\/\/s.ytimg.com\/yts\/img\/pixel-vfl3z5WfW.gif\" class=\"icon master-sprite\" alt=\"\uc54c\ub9bc \uc544\uc774\ucf58\"\u003e\n  \u003c\/div\u003e\n\u003cdiv class=\"yt-alert-buttons\"\u003e\u003c\/div\u003e\u003cdiv class=\"yt-alert-content\" role=\"alert\"\u003e    \u003cspan class=\"yt-alert-vertical-trick\"\u003e\u003c\/span\u003e\n    \u003cdiv class=\"yt-alert-message\"\u003e\n            \uc774 \ub3d9\uc601\uc0c1\uc744 \ubcf4\ub824\uba74 Adobe Flash Player\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \u003cbr\u003e\u003ca href=\"http:\/\/get.adobe.com\/flashplayer\/\"\u003eAdobe\uc5d0\uc11c \ub2e4\uc6b4\ub85c\ub4dc\ud558\uc138\uc694.\u003c\/a\u003e\n    \u003c\/div\u003e\n\u003c\/div\u003e\u003c\/div\u003e\u003c\/noembed\u003e\n\n";
        swf = swf.replace('__flashvars__', encoded.join('&'));
        document.getElementById('watch7-player').innerHTML = swf;
      })();
    </script>

embed 태그는 온데간데 없고, 이상한 자바스크립트 코드만 있습니다. 이게 어떻게 된 걸까요? 틀릴 리 없습니다. 이 자바스크립트 코드를 자세히 살펴 보면 답을 알아낼 수 있습니다. 우선 코드 마지막의 다음과 같은 코드를 주목합니다.

document.getElementById('watch7-player').innerHTML = swf;

즉 id가 watch7-player인 녀석의 내부 HTML 코드가 swf 변수의 내용이 됩니다. 위 그림을 보면 watch7-player id를 가진 div 태그의 자식이 embed이므로, swf 라는 변수에 틀림없이 embed 태그의 존재가 있을 겁니다. 윗줄의 swf 변수는 무언가 굉장히 복잡한 암호문처럼 보이지만 '<'나 '>'같은 문자 유니코드로 표현했을 때 그 문자에 대응되는 숫자를 16진수로 적은 것 뿐입니다. 이에 관해서는 ' Maniadb.com OpenAPI를 이용한 MP3 태그 검색기'의 인코딩 부분을 참고하세요. swf 변수의 내용을 보다 보기 쉽게 바꾸어 보려면 다음과 같은 파이썬 코딩을 하면 됩니다.

replace_swf_text.py
swf = "      \u003cembed type=\"application\/x-shockwave-flash\"     s\u0072c=\"http:\/\/s.ytimg.com\/yts\/swfbin\/watch_as3-vflXPuwnw.swf\"     id=\"movie_player\"    flashvars=\"__flashvars__\"     allowscriptaccess=\"always\" allowfullscreen=\"true\" bgcolor=\"#000000\"\u003e\n  \u003cnoembed\u003e\u003cdiv class=\"yt-alert yt-alert-default yt-alert-error  yt-alert-player\"\u003e  \u003cdiv class=\"yt-alert-icon\"\u003e\n    \u003cimg s\u0072c=\"\/\/s.ytimg.com\/yts\/img\/pixel-vfl3z5WfW.gif\" class=\"icon master-sprite\" alt=\"\uc54c\ub9bc \uc544\uc774\ucf58\"\u003e\n  \u003c\/div\u003e\n\u003cdiv class=\"yt-alert-buttons\"\u003e\u003c\/div\u003e\u003cdiv class=\"yt-alert-content\" role=\"alert\"\u003e    \u003cspan class=\"yt-alert-vertical-trick\"\u003e\u003c\/span\u003e\n    \u003cdiv class=\"yt-alert-message\"\u003e\n            \uc774 \ub3d9\uc601\uc0c1\uc744 \ubcf4\ub824\uba74 Adobe Flash Player\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \u003cbr\u003e\u003ca href=\"http:\/\/get.adobe.com\/flashplayer\/\"\u003eAdobe\uc5d0\uc11c \ub2e4\uc6b4\ub85c\ub4dc\ud558\uc138\uc694.\u003c\/a\u003e\n    \u003c\/div\u003e\n\u003c\/div\u003e\u003c\/div\u003e\u003c\/noembed\u003e\n\n"
 
print swf.decode('unicode-escape')

결과는 아래처럼 나옵니다. 그냥 전형적인 HTML embed 코드임을 알 수 있습니다.

      <embed type="application\/x-shockwave-flash"     src="http:\/\/s.ytimg.com\/yts\/swfbin\/watch_as3-vflXPuwnw.swf"     id="movie_player"    flashvars="__flashvars__"     allowscriptaccess="always" allowfullscreen="true" bgcolor="#000000">
  <noembed><div class="yt-alert yt-alert-default yt-alert-error  yt-alert-player">  <div class="yt-alert-icon">
    <img src="\/\/s.ytimg.com\/yts\/img\/pixel-vfl3z5WfW.gif" class="icon master-sprite" alt="알림 아이콘">
  <\/div>
<div class="yt-alert-buttons"><\/div><div class="yt-alert-content" role="alert">
    <span class="yt-alert-vertical-trick"><\/span>
    <div class="yt-alert-message">
            이 동영상을 보려면 Adobe Flash Player가 필요합니다. <br><a href="http:\/\/get.adobe.com\/flashplayer\/">Adobe에서 다운로드하세요.<\/a>
    <\/div>
<\/div><\/div><\/noembed>

아마 __flashvars__란 문자열은 swf = swf.replace('__flashvars__', encoded.join('&'));란 자바스크립트 코드에 의해 무언가 내용이 변화되었을 겁니다. 변화된 내용은 encoded라는 변수와 관련이 있을 것이고, 이것은 코드 좀 더 위에 있는 yt.playerConfig.args 란 부분과 깊은 관련이 있을 것입니다. 그러면 HTML 문서에서 playerConfig란 자바스크립트 변수를 찾아 보도록 하겠습니다. 제시한 위 자바스크립트 코드의 조금 윗부분에 아래와 같은 꽤 많은 양의 문자열을 발견할 수 있을 것입니다. 내용이 너무 길어 자세한 사항은 생략하겠습니다.

<div id="watch7-video-container">
      <div id="watch7-video">
            <script>
if (window.yt.timing) {yt.timing.tick("bf");}    </script>
 
            <script>
      yt.playerConfig = { ... };
    </script>

많은 내용들이 키=값 형태로 나열되어 있는 것을 확인할 수 있습니다. 일단 동영상을 다운로드 받는다는 목적에만 집중하겠습니다. 잡다한 키는 넘어가고 url_encoded_fmt_stream_map 이라는 키와 값에만 주목하도록 하겠습니다.

스트림 맵 분석하기

여기서는 url_encoded_fmt_stream_map의 값을 일컬어 '스트림 맵'이라고 부르겠습니다. 스트림 맵의 생짜 값(raw value)은 상당히 긴 문자열인데, 바로 여기에 우리가 원하는 동영상의 실제 주소가 숨겨져 있습니다. 이 문자열은 CSV 형태로 되어 있고, 각 필드의 값은 urlencode가 되어 있습니다. 일단 콤마(,)를 기준으로 문자열 분리를 해야 올바르게 하나의 의미를 가진 덩어리를 나눌 수 있습니다. 우선 당장 프로그래밍을 들이대지 말고 텍스트 편집기를 이용해 차근차근 손으로 해 보도록 하겠습니다.

스트림 맵을 텍스트 편집기로 붙여 넣습니다. 그리고 콤마 문자 하나를 검색합니다. 처음 발견된 콤마를 기준으로 공백을 입력해 값을 위, 아래 두 덩어리로 떼어 냅니다. 추출해 낸 윗부분 덩어리의 처음은 itag=XX\u0026sig=XXX… 와 같이 시작하는 것을 확인할 수 있습니다. \u0026은 유니코드 문자임이 분명합니다.

print unichr(0x26)

위 코드를 실행하면 '&' 문자가 출력됩니다. 그러므로 텍스트 편집기에서 \u0026을 찾아 '&'로 변경합니다. 변경할 때 '&' 기호 뒤에 개행 문자까지 넣으면 시각적으로 더 보기 좋겠죠. 그러면 다음과 같이 분리됩니다.

itag=...&
sig=...&
url=...&
fallback_host=...&
quality=...&
type=...,

이제 거의 다 왔습니다. url 부분이 보이죠? 바로 저기가 실제 동영상의 주소입니다. 나머지 분리하지 않은 덩어리도 같은 방식으로 나누어지므로 일일이 나누어 확인해 봅니다. 값을 다 살펴보면 아시겠지만, 서버가 다양한 포맷과 해상도로 인코딩해 놓은 것을 정리한 목록이 이 스트림 맵입니다. 결국 순수하게 HTML 코드 및 자바스크립트만 분석하면 동영상 주소를 찾아낼 수 있는 것이네요. 물론 이 방법이 언제까지 통하리란 보장은 없습니다만, 그렇다고 동영상의 주소를 숨바꼭질하는 것처럼 꽁꽁 숨겨두지는 않을 겁니다.

마지막으로 첫번째 덩어리의 url 부분의 문자열을 한 번 urldecode하면 웹브라우저에도 입력 가능한 url 주소가 됩니다. 단, 이 주소를 바로 넣으면 '403 forbidden' 에러가 납니다. 반드시 sig라는 키의 값을 붙여 넣어야 합니다. 주소로 적을 때는 왠일인지 키 이름은 sig에서 signature로 변경됩니다. 이렇게 signature까지 붙여 넣은 주소를 사용하면 동영상에 직접 접근이 가능합니다. 그러므로 이 주소만 있으면 HTTP 스트림 재생을 지원하는 다른 재생기에서도 재생이 가능하며, 우리의 최종 목적인 동영상 다운로드도 가능합니다. 이제 프로그램을 작성하기 위한 모든 준비가 끝났습니다.

코드로 작성

그러면 지금까지 한 내용을 파이썬 코드로 옮겨 보겠습니다. 완전 프로토타입의 코드이므로 쓰기 편하게 만드려면 고쳐야 할 부분이 많습니다. 그러나 일단 복잡한 기능은 배제하여 작동을 확인하는 수준으로 최대한 간결하게 작성해 보겠습니다.

youtube_dn_proto.py
# -*- coding: utf-8  -*-
import urllib
import urllib2
import re
import codecs
import sys
 
def get_html(url):
    # url을 열어 html 문서를 받아옵니다.
    # 문서는 utf-8 인코딩입니다.
    resp = urllib2.urlopen(url)
    html = resp.read().decode('utf-8')
 
    # 인코딩된 문서를 미리 저장하고, 저장된 문서를 이용합니다.
    # 일일이 네트워크를 이용해 문서를 받고 싶지 않을 때 사용합니다.
    # 적절히 주석으로 조절하세요.
    with codecs.open('sample.html', 'w', 'utf-8') as f:
        f.write(html)
 
    #with codecs.open('sample.html', 'r', 'utf-8') as f:
    #    html = f.read()
 
    return html
 
def extract_format_info(v_value):
    # v_value는 동영상의 아이디입니다.
    URL_BASE = 'http://www.youtube.com/watch?v='
    url      = URL_BASE + v_value
    html     = get_html(url)
 
    # playerConfig의 모든 값을 가져옵니다.
    t = re.search(r'yt.playerConfig = {(.+)};', html)
    # print t.groups()[0]
    # print
 
    # 그 중 스트림 맵 부분만 추출해냅니다.
    r = re.search(r'"url_encoded_fmt_stream_map": "(.+?)"', t.groups()[0].strip())
 
    # 스트림맵은 CSV이므로 콤마로 분리합니다.
    rawstrings = r.groups()[0].strip().split(',')
    items      = []
 
    for rawstring in rawstrings:
        item = {}
 
        # \uXXXX 부분을 실제 문자열로 변경합니다.
        uniesc = rawstring.decode('unicode-escape')
 
        # 실제 문자열로 변경된 부분 중 '&'기호가 있습니다.
        # 이것은 재차 키=값 문자열을 분리하는 역할을 합니다.
        for oneitem in uniesc.split('&'):
            # 키와 값을 분리, 딕셔너리로 저장합니다.
            key, val = oneitem.split('=')
            item[key] = urllib.unquote(val.strip())
 
        items.append(item)
 
    # 값들을 프린트
    #for item in items:
    #    for it in item.items():
    #        print it[0]+': '+it[1]
    #    print
 
    return items
 
if __name__ == '__main__':
    items  = extract_format_info(sys.argv[1])
 
    # 동영상을 실제로 받아 봅니다. url과 sig 필드의 값이 필요합니다.
    # 영상의 첫번째 항목을 열어 저장합니다.
    url    = '%s&signature=%s' % (items[0]['url'], items[0]['sig'])
 
    # 쿠키 등의 장치가 필요 없습니다. 단순히 열면 됩니다.
    resp   = urllib2.urlopen(url)
 
    # 수신 상태를 확인
    print resp.info()
 
    # 동영상의 인코딩 상태를 파악하여 다운로드 받는 것이 아니므로
    # 동영상 파일의 확장자는 적절히 변경하세요.
    f = open('result.flv', 'wb')
    f.write(resp.read())
    f.close()
    resp.close()

소스의 동영상 아이디만 적절히 바꾸면 파일이 다운로드 될 것입니다. 초라한 형태지만 제대로 동작함을 확인할 수 있습니다. 유튜브의 동영상 URL이 http://www.youtube.com/watch?v=a1cTyDOuop0라면

youtube_dn_proto.py a1cTyDOuop0

이렇게 입력하면 됩니다.

마치며

지금까지 간단하게 유튜브 동영상을 다운로드 받는 방법에 대해 조사하고 과정을 기록하였습니다. 다운로드를 할 수 있는 툴은 엄청나게 많지만 그 방법에 대해서 자세하게 소개한 문서가 없어 직접 해 보았습니다. 단순한 궁금증에서 시작했는데 은근히 재밌네요 

 기본적인 원리는 HTML 코드 파싱 –> 원하는 정보 추출 –> 다운로드로 별반 다른 것이 없습니다. 여타 프로그램들은 꽤 다양한 옵션들을 제공하고 쓰기도 편리하기도 할 겁니다. 그러나 기본적인 큰 틀은 제가 제시한 방법과 크게 다르지는 않을 것입니다.

마지막으로 파이썬 기반으로 작성된 유튜브와 같은 스트리밍 동영상의 다운로드 CLI 프로그램인 youtube-dl을 소개하고 문서를 마칩니다. 원클릭으로 실행되는 여타 다른 프로그램들 보다는 조금 불편하긴 합니다만, 유튜브 뿐만 아니라 다른 사이트의 동영상도 다운로드 가능하고, 여러 가지 옵션들이 잘 정리되어 있으며, 무엇보다 소스가 공개되어 있으므로 파이썬 공부를 위해서는 한 번 살펴볼만한 프로그램입니다.

반응형
반응형

플랫폼 다운로더란 유튜브, 틱톡, 비메오, 데일리모션 등의 미디어 플랫폼이나 인스타그램, 페이스북, 트위터 등의 소셜 네트워크 서비스, 혹은 레딧 등의 커뮤니티나 블로그 등의 온라인 플랫폼에서 다운로드를 제한하거나 막아둔 동영상, 사진, 음원 등의 콘텐츠를 다운로드할 수 있게 해주는 프로그램 혹은 웹사이트다.

대부분 다양한 다운로드 옵션을 제공한다. 예를 들면 동영상 다운뿐만 아니라 MP3 추출도 해주고, 유튜브 뿐만 아니라 인스타그램, 틱톡 등의 다양한 플랫폼 다운로드를 지원하며, 동영상의 해상도나 음원의 품질, 확장자도 설정할 수 있는 식이다. 무료 사이트도 많이 존재하지만 유료 사이트, 프로그램도 존재하며 초고화질 다운로드 등의 무료로는 쉽게 누리기 힘든 부가 기능을 제공한다. 화면이 작으면 초고화질이 뭔 소용인가 싶지만 모바일 유튜브 앱, 동영상 뷰어는 영상 확대 기능을 제공한다. 유튜브의 경우 플레이리스트의 전 영상을 한 번에 다운받게 해주는 사이트도 있다.

 

2.1. 대한민국 법률상 쟁점

저작권법 제30조(사적이용을 위한 복제)에 따르면 공개된 콘텐츠를 개인, 가정 및 이에 준하는 범위의 비영리 사적이용을 위해 다운로드받는 것이 혀용되지만, 콘텐츠 권리자측의 허락 없이는 영리 목적으로 사용하지 말고, 배포하지도 말고, 비영리적 개인소장 이외의 목적으로 사용하지 않아야 저작권, 초상권 등을 위반하지 않는다.

그러나 콘텐츠의 원본 파일에 접근할 수 없도록 기술적으로 보호되어 있는 플랫폼이 다수 존재하며, 일반적으로 이러한 경우가 플랫폼 다운로더를 사용하는 대상이 된다. 저작권법 제2조(정의) 28호에 따라 저작권법 및 저작권법이 보호하는 권리를 기술적 보호 조치를 허락 없이 고의나 과실로 제거, 변경하는 등으로 무력화하면 저작권법 제104조의2(기술적 보호조치의 무력화 금지)를 위반하게 되며, 예외 사항에 개인적 소장은 포함되어 있지 않으므로 원칙적으로 불법이다. 위반 시 저작권법 제136조(벌칙)에 의거하여 5년 이하의 징역, 5천만원 이하의 벌금에 처하거나 이를 병과할 수 있다.

하지만 저작권 제2조 28목 가항은 "저작권, 그 밖에 이 법에 따라 보호되는 권리의 행사와 관련하여 이 법에 따라 보호되는 저작물등에 대한 접근"에 대한 기술적 조치를 규정하고 있는데, 유튜브 원본파일이 아닌 유튜브에서 송신된 데이터는 유튜브 사이트나 앱을 통해 접근이 가능하고, 이를 원본으로 간주하는 판례는 존재하지 않으므로 플랫폼 다운로더가 플랫폼 서버에 저장된 원본파일 자체를 훔치는 방식이 아니라 콘텐츠 제공을 목적으로 송신된 데이터를 가공 등을 거쳐 다운받는 방식으로 작동한다면 개인, 가정 소장 목적으로 다운받는 것은 문제가 없을 듯 하다.

토렌트 등의 P2P 프로그램은 다운로드와 동시에 공유에 가담하도록 되어있으므로 저작권 상으로 문제가 되지만 P2P 자체는 플랫폼 다운로더가 아니므로 큰 관계는 없다.
반응형

+ Recent posts