Merge branch 'dev'
This commit is contained in:
420
README.md
420
README.md
@@ -1,12 +1,15 @@
|
|||||||
# youtube-dl_sjva
|
# youtube-dl_sjva
|
||||||
|
|
||||||
[SJVA](https://sjva.me/) 용 [youtube-dl](https://youtube-dl.org/) 플러그인입니다.
|
[SJVA](https://sjva.me/) 용 [youtube-dl](https://youtube-dl.org/) 플러그인입니다.
|
||||||
SJVA에서 유튜브, 네이버TV 등 동영상 사이트 영상을 다운로드할 수 있습니다.
|
SJVA에서 유튜브, 네이버TV 등 동영상 사이트 영상을 다운로드할 수 있습니다.
|
||||||
|
|
||||||
## 설치
|
## 설치
|
||||||
|
|
||||||
SJVA에서 "시스템 → 플러그인 → 플러그인 수동 설치" 칸에 저장소 주소를 넣고 설치 버튼을 누르면 됩니다.
|
SJVA에서 "시스템 → 플러그인 → 플러그인 수동 설치" 칸에 저장소 주소를 넣고 설치 버튼을 누르면 됩니다.
|
||||||
`https://github.com/joyfuI/youtube-dl`
|
`https://github.com/joyfuI/youtube-dl`
|
||||||
|
|
||||||
## 잡담
|
## 잡담
|
||||||
|
|
||||||
시놀로지 docker 환경에서 테스트했습니다.
|
시놀로지 docker 환경에서 테스트했습니다.
|
||||||
|
|
||||||
API를 제공합니다. 다른 플러그인에서 동영상 정보나 다운로드를 요청할 수 있습니다.
|
API를 제공합니다. 다른 플러그인에서 동영상 정보나 다운로드를 요청할 수 있습니다.
|
||||||
@@ -16,65 +19,80 @@ API를 제공합니다. 다른 플러그인에서 동영상 정보나 다운로
|
|||||||
설정에서 취향껏 골라서 사용하시면 되며 youtube-dl가 우선 지원됩니다.
|
설정에서 취향껏 골라서 사용하시면 되며 youtube-dl가 우선 지원됩니다.
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
### 공통사항
|
### 공통사항
|
||||||
|
|
||||||
모든 요청은 `POST` 또는 `GET`만 받습니다. 그리고 응답은 `JSON` 형식입니다.
|
모든 요청은 `POST` 또는 `GET`만 받습니다. 그리고 응답은 `JSON` 형식입니다.
|
||||||
모든 요청엔 *플러그인 이름* 정보가 있어야 합니다. `plugin` 키에 담아서 보내면 됩니다. 만약 *플러그인 이름* 정보가 없으면 **403 에러**를 반환합니다.
|
모든 요청엔 _플러그인 이름_ 정보가 있어야 합니다. `plugin` 키에 담아서 보내면 됩니다. 만약 _플러그인 이름_ 정보가 없으면 **403 에러**를 반환합니다.
|
||||||
요청을 처리하는 과정에서 예외가 발생하면 **500 에러**를 반환합니다. 이건 저한테 로그와 함께 알려주시면 됩니다.
|
요청을 처리하는 과정에서 예외가 발생하면 **500 에러**를 반환합니다. 이건 저한테 로그와 함께 알려주시면 됩니다.
|
||||||
모든 응답에는 `errorCode` 키가 있습니다. 코드의 의미는 아래 문단 참고
|
모든 응답에는 `errorCode` 키가 있습니다. 코드의 의미는 아래 문단 참고
|
||||||
|
|
||||||
#### 에러 코드 (errorCode)
|
#### 에러 코드 (errorCode)
|
||||||
* `0` - 성공. 문제없음
|
|
||||||
* `1` - 필수 요청 변수가 없음
|
- `0` - 성공. 문제없음
|
||||||
* `2` - 잘못된 동영상 주소
|
- `1` - 필수 요청 변수가 없음
|
||||||
* `3` - 인덱스 범위를 벗어남
|
- `2` - 잘못된 동영상 주소
|
||||||
* `4` - 키 값이 일치하지 않음
|
- `3` - 인덱스 범위를 벗어남
|
||||||
* `5` - 허용되지 않은 값이 있음
|
- `4` - 키 값이 일치하지 않음
|
||||||
* `10` - 실패. 요청은 성공하였으나 실행 결과가 실패
|
- `5` - 허용되지 않은 값이 있음
|
||||||
|
- `10` - 실패. 요청은 성공하였으나 실행 결과가 실패
|
||||||
|
|
||||||
#### Status 타입
|
#### Status 타입
|
||||||
|
|
||||||
상태를 나타냄
|
상태를 나타냄
|
||||||
* `"READY"` - 준비
|
|
||||||
* `"START"` - 분석중
|
- `"READY"` - 준비
|
||||||
* `"DOWNLOADING"` - 다운로드중
|
- `"START"` - 분석중
|
||||||
* `"ERROR"` - 실패
|
- `"DOWNLOADING"` - 다운로드중
|
||||||
* `"FINISHED"` - 변환중
|
- `"ERROR"` - 실패
|
||||||
* `"STOP"` - 중지
|
- `"FINISHED"` - 변환중
|
||||||
* `"COMPLETED"` - 완료
|
- `"STOP"` - 중지
|
||||||
|
- `"COMPLETED"` - 완료
|
||||||
|
|
||||||
### /youtube-dl/api/info_dict
|
### /youtube-dl/api/info_dict
|
||||||
|
|
||||||
동영상 정보를 반환하는 API
|
동영상 정보를 반환하는 API
|
||||||
|
|
||||||
#### Request
|
#### Request
|
||||||
키 | 설명 | 필수 | 타입
|
|
||||||
--- | --- | --- | ---
|
| 키 | 설명 | 필수 | 타입 |
|
||||||
`plugin` | 플러그인 이름 | O | String
|
| -------- | ------------- | ---- | ------ |
|
||||||
`url` | 동영상 주소 | O | String
|
| `plugin` | 플러그인 이름 | O | String |
|
||||||
|
| `url` | 동영상 주소 | O | String |
|
||||||
|
|
||||||
#### Response
|
#### Response
|
||||||
키 | 설명 | 타입
|
|
||||||
--- | --- | ---
|
| 키 | 설명 | 타입 |
|
||||||
`errorCode` | 에러 코드 | Integer
|
| ----------- | ----------- | ------- |
|
||||||
`info_dict` | 동영상 정보 | Object
|
| `errorCode` | 에러 코드 | Integer |
|
||||||
|
| `info_dict` | 동영상 정보 | Object |
|
||||||
|
|
||||||
동영상 정보(`info_dict` 키)에는 youtube-dl에서 생성한 info_dict 정보가 그대로 들어있습니다. 따라서 이 부분은 직접 주소를 넣어가며 반환되는 정보를 확인해보는 게 좋습니다.
|
동영상 정보(`info_dict` 키)에는 youtube-dl에서 생성한 info_dict 정보가 그대로 들어있습니다. 따라서 이 부분은 직접 주소를 넣어가며 반환되는 정보를 확인해보는 게 좋습니다.
|
||||||
간단한 예로 `thumbnail` 키엔 썸네일 주소, `uploader` 키엔 업로더 이름, `title` 키엔 동영상 제목, `duration` 키엔 동영상 길이 등이 들어 있습니다.
|
간단한 예로 `thumbnail` 키엔 썸네일 주소, `uploader` 키엔 업로더 이름, `title` 키엔 동영상 제목, `duration` 키엔 동영상 길이 등이 들어 있습니다.
|
||||||
그리고 만약 주소가 플레이리스트라면 `_type` 키에 `"playlist"`라는 값이 들어 있습니다. 이때는 `entries` 키에 리스트가 들어있어 동영상들의 제목과 ID를 확인할 수 있습니다.
|
그리고 만약 주소가 플레이리스트라면 `_type` 키에 `"playlist"`라는 값이 들어 있습니다. 이때는 `entries` 키에 리스트가 들어있어 동영상들의 제목과 ID를 확인할 수 있습니다.
|
||||||
|
|
||||||
### /youtube-dl/api/download
|
### /youtube-dl/api/download
|
||||||
|
|
||||||
비디오 다운로드 준비를 요청하는 API
|
비디오 다운로드 준비를 요청하는 API
|
||||||
|
|
||||||
#### Request
|
#### Request
|
||||||
키 | 설명 | 필수 | 타입
|
|
||||||
--- | --- | --- | ---
|
| 키 | 설명 | 필수 | 타입 |
|
||||||
`plugin` | 플러그인 이름 | O | String
|
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | ------- |
|
||||||
`key` | 임의의 키. 이후 다운로드를 제어할 때 이 키가 필요함 | O | String
|
| `plugin` | 플러그인 이름 | O | String |
|
||||||
`url` | 동영상 주소 | O | String
|
| `key` | 임의의 키. 이후 다운로드를 제어할 때 이 키가 필요함 | O | String |
|
||||||
`filename` | 파일명. 템플릿 규칙은 https://github.com/ytdl-org/youtube-dl/#output-template 참고. 미지정 시 사용자 설정 | X | String
|
| `url` | 동영상 주소 | O | String |
|
||||||
`save_path` | 저장 폴더 경로. 미지정 시 사용자 설정 | X | String
|
| `filename` | 파일명. 템플릿 규칙은 https://github.com/ytdl-org/youtube-dl/#output-template 참고. 미지정 시 사용자 설정 | X | String |
|
||||||
`format` | 동영상 포맷. 포맷 지정은 https://github.com/ytdl-org/youtube-dl/#format-selection 참고. 미지정 시 최고 화질 | X | String
|
| `save_path` | 저장 폴더 경로. 미지정 시 사용자 설정 | X | String |
|
||||||
`preferedformat` | 변환할 비디오 포맷. 가능한 포맷은 https://ffmpeg.org/general.html#File-Formats 참고. 미지정 시 변환하지 않음 | X | String
|
| `format` | 동영상 포맷. 포맷 지정은 https://github.com/ytdl-org/youtube-dl/#format-selection 참고. 미지정 시 최고 화질 | X | String |
|
||||||
`preferredcodec` | 추출할 오디오 코덱. 가능한 값은 `"best"`, `"mp3"`, `"aac"`, `"flac"`, `"m4a"`, `"opus"`, `"vorbis"`, `"wav"`. 미지정 시 추출하지 않음 | X | String
|
| `preferedformat` | 변환할 비디오 포맷. 가능한 포맷은 https://ffmpeg.org/general.html#File-Formats 참고. 미지정 시 변환하지 않음 | X | String |
|
||||||
`preferredquality` | 추출한 오디오의 비트레이트. 0 ~ 9 사이의 VBR 퀄리티 값(0에 가까울수록 좋음) 혹은 특정 비트레이트 값. `preferredcodec` 키가 있을 때만 유효. 기본값: `192` | X | Integer
|
| `preferredcodec` | 추출할 오디오 코덱. 가능한 값은 `"best"`, `"mp3"`, `"aac"`, `"flac"`, `"m4a"`, `"opus"`, `"vorbis"`, `"wav"`. 미지정 시 추출하지 않음 | X | String |
|
||||||
`dateafter` | 지정한 날짜 이후에 업로드된 동영상만 다운로드. 미지정 시 모두 다운로드 | X | String
|
| `preferredquality` | 추출한 오디오의 비트레이트. 0 ~ 9 사이의 VBR 퀄리티 값(0에 가까울수록 좋음) 혹은 특정 비트레이트 값. `preferredcodec` 키가 있을 때만 유효. 기본값: `192` | X | Integer |
|
||||||
`playlist` | 플레이리스트를 다운로드할 때 범위나 순서 지정. 미지정 시 모두 순서대로 다운로드 | X | String
|
| `dateafter` | 지정한 날짜 이후에 업로드된 동영상만 다운로드. 미지정 시 모두 다운로드 | X | String |
|
||||||
`archive` | 다운로드한 동영상의 ID를 기록할 파일 경로. 파일이 이미 있으면 이미 다운로드한 동영상은 다운로드 하지 않음. 미지정 시 기록하지 않음 | X | String
|
| `playlist` | 플레이리스트를 다운로드할 때 범위나 순서 지정. 미지정 시 모두 순서대로 다운로드 | X | String |
|
||||||
`start` | 다운로드 준비 후 바로 다운로드를 시작할지 여부. 기본값: `false` | X | Boolean
|
| `archive` | 다운로드한 동영상의 ID를 기록할 파일 경로. 파일이 이미 있으면 이미 다운로드한 동영상은 다운로드 하지 않음. 미지정 시 기록하지 않음 | X | String |
|
||||||
`cookiefile` | 다운로드 시 필요한 쿠키 파일 경로 | X | String
|
| `start` | 다운로드 준비 후 바로 다운로드를 시작할지 여부. 기본값: `false` | X | Boolean |
|
||||||
|
| `cookiefile` | 다운로드 시 필요한 쿠키 파일 경로 | X | String |
|
||||||
|
|
||||||
`dateafter` 키에 넣을 수 있는 날짜는 `"YYYYMMDD"` 또는 `"(now|today)[+-][0-9](day|week|month|year)(s)?"` 형식의 문자열입니다.
|
`dateafter` 키에 넣을 수 있는 날짜는 `"YYYYMMDD"` 또는 `"(now|today)[+-][0-9](day|week|month|year)(s)?"` 형식의 문자열입니다.
|
||||||
|
|
||||||
@@ -82,28 +100,33 @@ API를 제공합니다. 다른 플러그인에서 동영상 정보나 다운로
|
|||||||
범위를 넣으면 플레이리스트에서 선택한 것만 다운로드합니다.
|
범위를 넣으면 플레이리스트에서 선택한 것만 다운로드합니다.
|
||||||
`"reverse"`를 넣으면 전체 플레이리스트를 역순으로 다운로드합니다.
|
`"reverse"`를 넣으면 전체 플레이리스트를 역순으로 다운로드합니다.
|
||||||
`"random"`을 넣으면 전체 플레이리스트를 랜덤 순서로 다운로드합니다.
|
`"random"`을 넣으면 전체 플레이리스트를 랜덤 순서로 다운로드합니다.
|
||||||
|
|
||||||
#### Response
|
#### Response
|
||||||
키 | 설명 | 타입
|
|
||||||
--- | --- | ---
|
| 키 | 설명 | 타입 |
|
||||||
`errorCode` | 에러 코드 | Integer
|
| ----------- | ------------------------------------------------------- | ------- |
|
||||||
`index` | 동영상 인덱스. 이후 다운로드를 제어할 때 이 값이 필요함 | Integer
|
| `errorCode` | 에러 코드 | Integer |
|
||||||
|
| `index` | 동영상 인덱스. 이후 다운로드를 제어할 때 이 값이 필요함 | Integer |
|
||||||
|
|
||||||
### /youtube-dl/api/thumbnail
|
### /youtube-dl/api/thumbnail
|
||||||
|
|
||||||
썸네일 다운로드 준비를 요청하는 API
|
썸네일 다운로드 준비를 요청하는 API
|
||||||
|
|
||||||
#### Request
|
#### Request
|
||||||
키 | 설명 | 필수 | 타입
|
|
||||||
--- | --- | --- | ---
|
| 키 | 설명 | 필수 | 타입 |
|
||||||
`plugin` | 플러그인 이름 | O | String
|
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---- | ------- |
|
||||||
`key` | 임의의 키. 이후 다운로드를 제어할 때 이 키가 필요함 | O | String
|
| `plugin` | 플러그인 이름 | O | String |
|
||||||
`url` | 동영상 주소 | O | String
|
| `key` | 임의의 키. 이후 다운로드를 제어할 때 이 키가 필요함 | O | String |
|
||||||
`filename` | 파일명. 템플릿 규칙은 https://github.com/ytdl-org/youtube-dl/#output-template 참고. 미지정 시 사용자 설정 | X | String
|
| `url` | 동영상 주소 | O | String |
|
||||||
`save_path` | 저장 폴더 경로. 미지정 시 사용자 설정 | X | String
|
| `filename` | 파일명. 템플릿 규칙은 https://github.com/ytdl-org/youtube-dl/#output-template 참고. 미지정 시 사용자 설정 | X | String |
|
||||||
`all_thumbnails` | 모든 썸네일 다운로드 여부. `false`는 대표 썸네일 하나만 다운로드. 기본값: `false` | X | Boolean
|
| `save_path` | 저장 폴더 경로. 미지정 시 사용자 설정 | X | String |
|
||||||
`dateafter` | 지정한 날짜 이후에 업로드된 동영상만 다운로드. 미지정 시 모두 다운로드 | X | String
|
| `all_thumbnails` | 모든 썸네일 다운로드 여부. `false`는 대표 썸네일 하나만 다운로드. 기본값: `false` | X | Boolean |
|
||||||
`playlist` | 플레이리스트를 다운로드할 때 범위나 순서 지정. 미지정 시 모두 순서대로 다운로드 | X | String
|
| `dateafter` | 지정한 날짜 이후에 업로드된 동영상만 다운로드. 미지정 시 모두 다운로드 | X | String |
|
||||||
`archive` | 다운로드한 동영상의 ID를 기록할 파일 경로. 파일이 이미 있으면 이미 다운로드한 동영상은 다운로드 하지 않음. 미지정 시 기록하지 않음 | X | String
|
| `playlist` | 플레이리스트를 다운로드할 때 범위나 순서 지정. 미지정 시 모두 순서대로 다운로드 | X | String |
|
||||||
`start` | 다운로드 준비 후 바로 다운로드를 시작할지 여부. 기본값: `false` | X | Boolean
|
| `archive` | 다운로드한 동영상의 ID를 기록할 파일 경로. 파일이 이미 있으면 이미 다운로드한 동영상은 다운로드 하지 않음. 미지정 시 기록하지 않음 | X | String |
|
||||||
`cookiefile` | 다운로드 시 필요한 쿠키 파일 경로 | X | String
|
| `start` | 다운로드 준비 후 바로 다운로드를 시작할지 여부. 기본값: `false` | X | Boolean |
|
||||||
|
| `cookiefile` | 다운로드 시 필요한 쿠키 파일 경로 | X | String |
|
||||||
|
|
||||||
`dateafter` 키에 넣을 수 있는 날짜는 `"YYYYMMDD"` 또는 `"(now|today)[+-][0-9](day|week|month|year)(s)?"` 형식의 문자열입니다.
|
`dateafter` 키에 넣을 수 있는 날짜는 `"YYYYMMDD"` 또는 `"(now|today)[+-][0-9](day|week|month|year)(s)?"` 형식의 문자열입니다.
|
||||||
|
|
||||||
@@ -111,30 +134,35 @@ API를 제공합니다. 다른 플러그인에서 동영상 정보나 다운로
|
|||||||
범위를 넣으면 플레이리스트에서 선택한 것만 다운로드합니다.
|
범위를 넣으면 플레이리스트에서 선택한 것만 다운로드합니다.
|
||||||
`"reverse"`를 넣으면 전체 플레이리스트를 역순으로 다운로드합니다.
|
`"reverse"`를 넣으면 전체 플레이리스트를 역순으로 다운로드합니다.
|
||||||
`"random"`을 넣으면 전체 플레이리스트를 랜덤 순서로 다운로드합니다.
|
`"random"`을 넣으면 전체 플레이리스트를 랜덤 순서로 다운로드합니다.
|
||||||
|
|
||||||
#### Response
|
#### Response
|
||||||
키 | 설명 | 타입
|
|
||||||
--- | --- | ---
|
| 키 | 설명 | 타입 |
|
||||||
`errorCode` | 에러 코드 | Integer
|
| ----------- | ------------------------------------------------------- | ------- |
|
||||||
`index` | 동영상 인덱스. 이후 다운로드를 제어할 때 이 값이 필요함 | Integer
|
| `errorCode` | 에러 코드 | Integer |
|
||||||
|
| `index` | 동영상 인덱스. 이후 다운로드를 제어할 때 이 값이 필요함 | Integer |
|
||||||
|
|
||||||
### /youtube-dl/api/sub
|
### /youtube-dl/api/sub
|
||||||
|
|
||||||
자막 다운로드 준비를 요청하는 API
|
자막 다운로드 준비를 요청하는 API
|
||||||
|
|
||||||
#### Request
|
#### Request
|
||||||
키 | 설명 | 필수 | 타입
|
|
||||||
--- | --- | --- | ---
|
| 키 | 설명 | 필수 | 타입 |
|
||||||
`plugin` | 플러그인 이름 | O | String
|
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ---- | ------- |
|
||||||
`key` | 임의의 키. 이후 다운로드를 제어할 때 이 키가 필요함 | O | String
|
| `plugin` | 플러그인 이름 | O | String |
|
||||||
`url` | 동영상 주소 | O | String
|
| `key` | 임의의 키. 이후 다운로드를 제어할 때 이 키가 필요함 | O | String |
|
||||||
`filename` | 파일명. 템플릿 규칙은 https://github.com/ytdl-org/youtube-dl/#output-template 참고. 미지정 시 사용자 설정 | X | String
|
| `url` | 동영상 주소 | O | String |
|
||||||
`save_path` | 저장 폴더 경로. 미지정 시 사용자 설정 | X | String
|
| `filename` | 파일명. 템플릿 규칙은 https://github.com/ytdl-org/youtube-dl/#output-template 참고. 미지정 시 사용자 설정 | X | String |
|
||||||
`all_subs` | 모든 자막 다운로드 여부. 기본값: `false` | X | Boolean
|
| `save_path` | 저장 폴더 경로. 미지정 시 사용자 설정 | X | String |
|
||||||
`sub_lang` | 자막 언어. 두 자리 국가 코드. 콤마(,)를 구분자로 여러 개 지정 가능. `all_subs` 키가 `false`일 때만 유효. 기본값: `"ko"` | X | String
|
| `all_subs` | 모든 자막 다운로드 여부. 기본값: `false` | X | Boolean |
|
||||||
`auto_sub` | 자동생성 자막 다운로드 여부. 유튜브 전용. 기본값: `false` | X | Boolean
|
| `sub_lang` | 자막 언어. 두 자리 국가 코드. 콤마(,)를 구분자로 여러 개 지정 가능. `all_subs` 키가 `false`일 때만 유효. 기본값: `"ko"` | X | String |
|
||||||
`dateafter` | 지정한 날짜 이후에 업로드된 동영상만 다운로드. 미지정 시 모두 다운로드 | X | String
|
| `auto_sub` | 자동생성 자막 다운로드 여부. 유튜브 전용. 기본값: `false` | X | Boolean |
|
||||||
`playlist` | 플레이리스트를 다운로드할 때 범위나 순서 지정. 미지정 시 모두 순서대로 다운로드 | X | String
|
| `dateafter` | 지정한 날짜 이후에 업로드된 동영상만 다운로드. 미지정 시 모두 다운로드 | X | String |
|
||||||
`archive` | 다운로드한 동영상의 ID를 기록할 파일 경로. 파일이 이미 있으면 이미 다운로드한 동영상은 다운로드 하지 않음. 미지정 시 기록하지 않음 | X | String
|
| `playlist` | 플레이리스트를 다운로드할 때 범위나 순서 지정. 미지정 시 모두 순서대로 다운로드 | X | String |
|
||||||
`start` | 다운로드 준비 후 바로 다운로드를 시작할지 여부. 기본값: `false` | X | Boolean
|
| `archive` | 다운로드한 동영상의 ID를 기록할 파일 경로. 파일이 이미 있으면 이미 다운로드한 동영상은 다운로드 하지 않음. 미지정 시 기록하지 않음 | X | String |
|
||||||
`cookiefile` | 다운로드 시 필요한 쿠키 파일 경로 | X | String
|
| `start` | 다운로드 준비 후 바로 다운로드를 시작할지 여부. 기본값: `false` | X | Boolean |
|
||||||
|
| `cookiefile` | 다운로드 시 필요한 쿠키 파일 경로 | X | String |
|
||||||
|
|
||||||
`dateafter` 키에 넣을 수 있는 날짜는 `"YYYYMMDD"` 또는 `"(now|today)[+-][0-9](day|week|month|year)(s)?"` 형식의 문자열입니다.
|
`dateafter` 키에 넣을 수 있는 날짜는 `"YYYYMMDD"` 또는 `"(now|today)[+-][0-9](day|week|month|year)(s)?"` 형식의 문자열입니다.
|
||||||
|
|
||||||
@@ -142,227 +170,287 @@ API를 제공합니다. 다른 플러그인에서 동영상 정보나 다운로
|
|||||||
범위를 넣으면 플레이리스트에서 선택한 것만 다운로드합니다.
|
범위를 넣으면 플레이리스트에서 선택한 것만 다운로드합니다.
|
||||||
`"reverse"`를 넣으면 전체 플레이리스트를 역순으로 다운로드합니다.
|
`"reverse"`를 넣으면 전체 플레이리스트를 역순으로 다운로드합니다.
|
||||||
`"random"`을 넣으면 전체 플레이리스트를 랜덤 순서로 다운로드합니다.
|
`"random"`을 넣으면 전체 플레이리스트를 랜덤 순서로 다운로드합니다.
|
||||||
|
|
||||||
#### Response
|
#### Response
|
||||||
키 | 설명 | 타입
|
|
||||||
--- | --- | ---
|
| 키 | 설명 | 타입 |
|
||||||
`errorCode` | 에러 코드 | Integer
|
| ----------- | ------------------------------------------------------- | ------- |
|
||||||
`index` | 동영상 인덱스. 이후 다운로드를 제어할 때 이 값이 필요함 | Integer
|
| `errorCode` | 에러 코드 | Integer |
|
||||||
|
| `index` | 동영상 인덱스. 이후 다운로드를 제어할 때 이 값이 필요함 | Integer |
|
||||||
|
|
||||||
### /youtube-dl/api/start
|
### /youtube-dl/api/start
|
||||||
|
|
||||||
다운로드 시작을 요청하는 API
|
다운로드 시작을 요청하는 API
|
||||||
|
|
||||||
#### Request
|
#### Request
|
||||||
키 | 설명 | 필수 | 타입
|
|
||||||
--- | --- | --- | ---
|
| 키 | 설명 | 필수 | 타입 |
|
||||||
`plugin` | 플러그인 이름 | O | String
|
| -------- | ----------------------------------------------------------- | ---- | ------- |
|
||||||
`index` | 제어할 동영상의 인덱스 | O | Integer
|
| `plugin` | 플러그인 이름 | O | String |
|
||||||
`key` | 제어할 동영상에게 넘겨준 키. 이 값이 일치해야 요청이 실행됨 | O | String
|
| `index` | 제어할 동영상의 인덱스 | O | Integer |
|
||||||
|
| `key` | 제어할 동영상에게 넘겨준 키. 이 값이 일치해야 요청이 실행됨 | O | String |
|
||||||
|
|
||||||
#### Response
|
#### Response
|
||||||
키 | 설명 | 타입
|
|
||||||
--- | --- | ---
|
| 키 | 설명 | 타입 |
|
||||||
`errorCode` | 에러 코드 | Integer
|
| ----------- | ------------------------- | ------- |
|
||||||
`status` | 요청을 받았을 당시의 상태 | Status
|
| `errorCode` | 에러 코드 | Integer |
|
||||||
|
| `status` | 요청을 받았을 당시의 상태 | Status |
|
||||||
|
|
||||||
### /youtube-dl/api/stop
|
### /youtube-dl/api/stop
|
||||||
|
|
||||||
다운로드 중지를 요청하는 API
|
다운로드 중지를 요청하는 API
|
||||||
|
|
||||||
#### Request
|
#### Request
|
||||||
키 | 설명 | 필수 | 타입
|
|
||||||
--- | --- | --- | ---
|
| 키 | 설명 | 필수 | 타입 |
|
||||||
`plugin` | 플러그인 이름 | O | String
|
| -------- | ----------------------------------------------------------- | ---- | ------- |
|
||||||
`index` | 제어할 동영상의 인덱스 | O | Integer
|
| `plugin` | 플러그인 이름 | O | String |
|
||||||
`key` | 제어할 동영상에게 넘겨준 키. 이 값이 일치해야 요청이 실행됨 | O | String
|
| `index` | 제어할 동영상의 인덱스 | O | Integer |
|
||||||
|
| `key` | 제어할 동영상에게 넘겨준 키. 이 값이 일치해야 요청이 실행됨 | O | String |
|
||||||
|
|
||||||
#### Response
|
#### Response
|
||||||
키 | 설명 | 타입
|
|
||||||
--- | --- | ---
|
| 키 | 설명 | 타입 |
|
||||||
`errorCode` | 에러 코드 | Integer
|
| ----------- | ------------------------- | ------- |
|
||||||
`status` | 요청을 받았을 당시의 상태 | Status
|
| `errorCode` | 에러 코드 | Integer |
|
||||||
|
| `status` | 요청을 받았을 당시의 상태 | Status |
|
||||||
|
|
||||||
### /youtube-dl/api/status
|
### /youtube-dl/api/status
|
||||||
|
|
||||||
현재 상태를 반환하는 API
|
현재 상태를 반환하는 API
|
||||||
|
|
||||||
#### Request
|
#### Request
|
||||||
키 | 설명 | 필수 | 타입
|
|
||||||
--- | --- | --- | ---
|
| 키 | 설명 | 필수 | 타입 |
|
||||||
`plugin` | 플러그인 이름 | O | String
|
| -------- | ----------------------------------------------------------- | ---- | ------- |
|
||||||
`index` | 제어할 동영상의 인덱스 | O | Integer
|
| `plugin` | 플러그인 이름 | O | String |
|
||||||
`key` | 제어할 동영상에게 넘겨준 키. 이 값이 일치해야 요청이 실행됨 | O | String
|
| `index` | 제어할 동영상의 인덱스 | O | Integer |
|
||||||
|
| `key` | 제어할 동영상에게 넘겨준 키. 이 값이 일치해야 요청이 실행됨 | O | String |
|
||||||
|
|
||||||
#### Response
|
#### Response
|
||||||
키 | 설명 | 타입
|
|
||||||
--- | --- | ---
|
| 키 | 설명 | 타입 |
|
||||||
`errorCode` | 에러 코드 | Integer
|
| ------------ | ----------------------------------------------- | ------- |
|
||||||
`status` | 요청을 받았을 당시의 상태 | Status
|
| `errorCode` | 에러 코드 | Integer |
|
||||||
`type` | 다운로드 타입. `"video" "thumbnail" "subtitle"` | String
|
| `status` | 요청을 받았을 당시의 상태 | Status |
|
||||||
`start_time` | 다운로드 시작 시간 | String
|
| `type` | 다운로드 타입. `"video" "thumbnail" "subtitle"` | String |
|
||||||
`end_time` | 다운로드 종료 시간 | String
|
| `start_time` | 다운로드 시작 시간 | String |
|
||||||
`temp_path` | 임시 폴더 경로 | String
|
| `end_time` | 다운로드 종료 시간 | String |
|
||||||
`save_path` | 저장 폴더 경로 | String
|
| `temp_path` | 임시 폴더 경로 | String |
|
||||||
|
| `save_path` | 저장 폴더 경로 | String |
|
||||||
|
|
||||||
`start_time` 키와 `end_time` 키에 들어있는 시간은 `"YYYY-MM-DDThh:mm:ss"` 형식의 문자열입니다.
|
`start_time` 키와 `end_time` 키에 들어있는 시간은 `"YYYY-MM-DDThh:mm:ss"` 형식의 문자열입니다.
|
||||||
물론 해당 정보가 없으면 null입니다.
|
물론 해당 정보가 없으면 null입니다.
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
v3.1.0
|
||||||
|
|
||||||
|
- yt-dlp일 때 작동 안하는 문제 수정
|
||||||
|
|
||||||
v3.0.1
|
v3.0.1
|
||||||
* 다운로드 후 파일 이동이 안되던 문제 수정
|
|
||||||
|
- 다운로드 후 파일 이동이 안되던 문제 수정
|
||||||
|
|
||||||
v3.0.0
|
v3.0.0
|
||||||
* SJVA3 대응
|
|
||||||
* SJVA에 flask_cors가 내장됨에 따라 항상 CORS 허용
|
- SJVA3 대응
|
||||||
|
- SJVA에 flask_cors가 내장됨에 따라 항상 CORS 허용
|
||||||
|
|
||||||
v2.4.0
|
v2.4.0
|
||||||
* API에 playlist 키 추가
|
|
||||||
|
- API에 playlist 키 추가
|
||||||
플레이리스트 다운로드 시 범위나 순서를 지정할 수 있습니다.
|
플레이리스트 다운로드 시 범위나 순서를 지정할 수 있습니다.
|
||||||
* 썸네일 다운로드 기능 추가
|
- 썸네일 다운로드 기능 추가
|
||||||
* thumbnail API 추가
|
- thumbnail API 추가
|
||||||
* 자막 다운로드 기능 추가
|
- 자막 다운로드 기능 추가
|
||||||
* sub API 추가
|
- sub API 추가
|
||||||
* 설정에 경로 선택 버튼 추가
|
- 설정에 경로 선택 버튼 추가
|
||||||
|
|
||||||
v2.3.1
|
v2.3.1
|
||||||
* yt-dlp 패키지명 변경 대응
|
|
||||||
|
- yt-dlp 패키지명 변경 대응
|
||||||
|
|
||||||
v2.3.0
|
v2.3.0
|
||||||
* youtube-dlc를 yt-dlp로 변경
|
|
||||||
|
- youtube-dlc를 yt-dlp로 변경
|
||||||
youtube-dlc가 2개월 넘게 커밋이 없어서 youtube-dlc의 포크 프로젝트인 yt-dlp로 변경했습니다.
|
youtube-dlc가 2개월 넘게 커밋이 없어서 youtube-dlc의 포크 프로젝트인 yt-dlp로 변경했습니다.
|
||||||
기존에 youtube-dlc로 사용하던 분들은 yt-dlp로 변경됩니다.
|
기존에 youtube-dlc로 사용하던 분들은 yt-dlp로 변경됩니다.
|
||||||
|
|
||||||
v2.2.0
|
v2.2.0
|
||||||
* download API의 headers 키 제거
|
|
||||||
|
- download API의 headers 키 제거
|
||||||
|
|
||||||
v2.1.2
|
v2.1.2
|
||||||
* youtube-dlc 호환 문제 수정
|
|
||||||
|
- youtube-dlc 호환 문제 수정
|
||||||
|
|
||||||
v2.1.1
|
v2.1.1
|
||||||
|
|
||||||
v2.1.0
|
v2.1.0
|
||||||
* download API에 cookiefile, headers 키 추가
|
|
||||||
|
- download API에 cookiefile, headers 키 추가
|
||||||
카카오TV 동영상 다운로드에 활용할 수 있습니다. 잘하면 로봇 체크 패스에도 사용이 가능한 듯 싶습니다.
|
카카오TV 동영상 다운로드에 활용할 수 있습니다. 잘하면 로봇 체크 패스에도 사용이 가능한 듯 싶습니다.
|
||||||
Thanks to [soju6jan](https://github.com/soju6jan)
|
Thanks to [soju6jan](https://github.com/soju6jan)
|
||||||
|
|
||||||
v2.0.0
|
v2.0.0
|
||||||
* youtube-dlc 추가
|
|
||||||
|
- youtube-dlc 추가
|
||||||
사용할 youtube-dl 패키지를 선택할 수 있습니다. 설정 변경 후 재시작해야 적용됩니다.
|
사용할 youtube-dl 패키지를 선택할 수 있습니다. 설정 변경 후 재시작해야 적용됩니다.
|
||||||
|
|
||||||
v1.7.0
|
v1.7.0
|
||||||
* Python 3 지원
|
|
||||||
|
- Python 3 지원
|
||||||
Python 2를 유지한 채로 Python 3 지원을 추가했습니다.
|
Python 2를 유지한 채로 Python 3 지원을 추가했습니다.
|
||||||
* download API에 dateafter 추가
|
- download API에 dateafter 추가
|
||||||
지정한 날짜 이후에 업로드된 동영상만 다운로드하는 옵션입니다. 플레이리스트 다운로드 시에 유용하게 사용할 수 있습니다.
|
지정한 날짜 이후에 업로드된 동영상만 다운로드하는 옵션입니다. 플레이리스트 다운로드 시에 유용하게 사용할 수 있습니다.
|
||||||
|
|
||||||
v1.6.11
|
v1.6.11
|
||||||
* 목록 메뉴에 전체 중지 버튼 추가
|
|
||||||
|
- 목록 메뉴에 전체 중지 버튼 추가
|
||||||
|
|
||||||
v1.6.10
|
v1.6.10
|
||||||
* CORS 허용 설정이 작동하지 않는 문제 수정
|
|
||||||
|
- CORS 허용 설정이 작동하지 않는 문제 수정
|
||||||
Thanks to [dbswnschl](https://github.com/dbswnschl)
|
Thanks to [dbswnschl](https://github.com/dbswnschl)
|
||||||
|
|
||||||
v1.6.9
|
v1.6.9
|
||||||
* 일부 동영상 사이트에서 다운로드 실패하는 문제 수정
|
|
||||||
|
- 일부 동영상 사이트에서 다운로드 실패하는 문제 수정
|
||||||
|
|
||||||
v1.6.8
|
v1.6.8
|
||||||
* download API에서 filename 키가 적용되지 않는 문제 수정
|
|
||||||
|
- download API에서 filename 키가 적용되지 않는 문제 수정
|
||||||
|
|
||||||
v1.6.7
|
v1.6.7
|
||||||
* 일부 상황에서 다운로드가 완료로 표시되지 않는 문제 수정
|
|
||||||
|
- 일부 상황에서 다운로드가 완료로 표시되지 않는 문제 수정
|
||||||
|
|
||||||
v1.6.6
|
v1.6.6
|
||||||
|
|
||||||
v1.6.5
|
v1.6.5
|
||||||
* info_dict API가 동작하지 않는 문제 수정
|
|
||||||
|
- info_dict API가 동작하지 않는 문제 수정
|
||||||
|
|
||||||
v1.6.4
|
v1.6.4
|
||||||
* FFmpeg 경로 설정 추가
|
|
||||||
|
- FFmpeg 경로 설정 추가
|
||||||
SJVA에 내장된 버전 말고 원하는 버전을 사용할 수 있습니다.
|
SJVA에 내장된 버전 말고 원하는 버전을 사용할 수 있습니다.
|
||||||
* API에서 GET 요청 지원
|
- API에서 GET 요청 지원
|
||||||
이제 GET 요청으로도 API를 사용할 수 있습니다.
|
이제 GET 요청으로도 API를 사용할 수 있습니다.
|
||||||
|
|
||||||
v1.6.3
|
v1.6.3
|
||||||
* 프록시 기능을 사용해도 국가차단 우회가 안 되는 문제 수정
|
|
||||||
|
- 프록시 기능을 사용해도 국가차단 우회가 안 되는 문제 수정
|
||||||
|
|
||||||
v1.6.2
|
v1.6.2
|
||||||
|
|
||||||
v1.6.1
|
v1.6.1
|
||||||
|
|
||||||
v1.6.0
|
v1.6.0
|
||||||
* API에 format_code를 format으로 변경
|
|
||||||
* API에 temp_path 삭제
|
- API에 format_code를 format으로 변경
|
||||||
|
- API에 temp_path 삭제
|
||||||
|
|
||||||
v1.5.1
|
v1.5.1
|
||||||
|
|
||||||
v1.5.0
|
v1.5.0
|
||||||
* 프록시 설정 추가
|
|
||||||
* API에 archive 추가
|
- 프록시 설정 추가
|
||||||
|
- API에 archive 추가
|
||||||
download-archive 기능으로 다운로드한 동영상의 ID를 기록하여 이미 다운로드한 동영상은 다운로드 하지 않는 옵션입니다.
|
download-archive 기능으로 다운로드한 동영상의 ID를 기록하여 이미 다운로드한 동영상은 다운로드 하지 않는 옵션입니다.
|
||||||
* status API의 시간 형식 변경 (ISO 8601)
|
- status API의 시간 형식 변경 (ISO 8601)
|
||||||
|
|
||||||
v1.4.2
|
v1.4.2
|
||||||
* --rm-cache-dir 옵션 추가
|
|
||||||
* 플러그인 최초 설치 시 작동 안 되는 문제 수정
|
- --rm-cache-dir 옵션 추가
|
||||||
|
- 플러그인 최초 설치 시 작동 안 되는 문제 수정
|
||||||
|
|
||||||
v1.4.1
|
v1.4.1
|
||||||
* CORS 허용 설정 추가
|
|
||||||
|
- CORS 허용 설정 추가
|
||||||
Thanks to [dbswnschl](https://github.com/dbswnschl)
|
Thanks to [dbswnschl](https://github.com/dbswnschl)
|
||||||
|
|
||||||
v1.4.0
|
v1.4.0
|
||||||
* socketio 적용
|
|
||||||
|
- socketio 적용
|
||||||
목록 페이지에서 목록이 실시간으로 업데이트됩니다.
|
목록 페이지에서 목록이 실시간으로 업데이트됩니다.
|
||||||
|
|
||||||
v1.3.5
|
v1.3.5
|
||||||
|
|
||||||
v1.3.4
|
v1.3.4
|
||||||
* 플러그인 구조를 가이드에 맞춰 변경
|
|
||||||
|
- 플러그인 구조를 가이드에 맞춰 변경
|
||||||
플러그인 설정이 초기화됩니다.
|
플러그인 설정이 초기화됩니다.
|
||||||
|
|
||||||
v1.3.3
|
v1.3.3
|
||||||
* API 변경
|
|
||||||
|
- API 변경
|
||||||
|
|
||||||
v1.3.2
|
v1.3.2
|
||||||
* 파일명에 경로 지정 시 이미 존재하는 경로면 에러가 발생하는 문제 수정
|
|
||||||
* celery 적용
|
- 파일명에 경로 지정 시 이미 존재하는 경로면 에러가 발생하는 문제 수정
|
||||||
|
- celery 적용
|
||||||
|
|
||||||
v1.3.1
|
v1.3.1
|
||||||
|
|
||||||
v1.3.0
|
v1.3.0
|
||||||
* 후처리 기능 추가
|
|
||||||
|
- 후처리 기능 추가
|
||||||
이제 비디오 변환이나 오디오 추출이 가능합니다.
|
이제 비디오 변환이나 오디오 추출이 가능합니다.
|
||||||
오디오 추출의 비트레이트는 192kbps로 설정되어 있습니다.
|
오디오 추출의 비트레이트는 192kbps로 설정되어 있습니다.
|
||||||
|
|
||||||
v1.2.5
|
v1.2.5
|
||||||
* 기본 파일명 설정 추가
|
|
||||||
* API에서 일부 키를 선택으로 변경
|
- 기본 파일명 설정 추가
|
||||||
|
- API에서 일부 키를 선택으로 변경
|
||||||
|
|
||||||
v1.2.4
|
v1.2.4
|
||||||
* API Key 기능 추가
|
|
||||||
|
- API Key 기능 추가
|
||||||
|
|
||||||
v1.2.3
|
v1.2.3
|
||||||
* 저장 경로가 존재하지 않으면 생성하도록 개선
|
|
||||||
|
- 저장 경로가 존재하지 않으면 생성하도록 개선
|
||||||
|
|
||||||
v1.2.2
|
v1.2.2
|
||||||
* youtube-dl 패키지 업그레이드도 로그 찍히도록 수정
|
|
||||||
|
- youtube-dl 패키지 업그레이드도 로그 찍히도록 수정
|
||||||
|
|
||||||
v1.2.1
|
v1.2.1
|
||||||
|
|
||||||
v1.2.0
|
v1.2.0
|
||||||
* API 추가
|
|
||||||
|
- API 추가
|
||||||
이제 다른 플러그인에서 동영상 정보 가져오기, 다운로드 요청이 가능합니다.
|
이제 다른 플러그인에서 동영상 정보 가져오기, 다운로드 요청이 가능합니다.
|
||||||
자세한 명세는 API 문단을 참고하세요.
|
자세한 명세는 API 문단을 참고하세요.
|
||||||
|
|
||||||
v1.1.1
|
v1.1.1
|
||||||
* 플레이리스트 다운로드 중 국가차단 등의 이유로 다운로드 실패한 동영상이 있으면 건너뛰도록 개선
|
|
||||||
|
- 플레이리스트 다운로드 중 국가차단 등의 이유로 다운로드 실패한 동영상이 있으면 건너뛰도록 개선
|
||||||
|
|
||||||
v1.1.0
|
v1.1.0
|
||||||
* 화질 선택 기능 추가
|
|
||||||
* 잘못된 예외처리 수정
|
- 화질 선택 기능 추가
|
||||||
|
- 잘못된 예외처리 수정
|
||||||
|
|
||||||
v1.0.2
|
v1.0.2
|
||||||
|
|
||||||
v1.0.1
|
v1.0.1
|
||||||
* 로그 좀 더 상세히 찍도록 수정
|
|
||||||
|
- 로그 좀 더 상세히 찍도록 수정
|
||||||
|
|
||||||
v1.0.0
|
v1.0.0
|
||||||
* 바이너리 실행 방식에서 파이썬 임베딩 방식으로 변경
|
|
||||||
* SJVA 시작 시 자동으로 youtube-dl 업데이트
|
- 바이너리 실행 방식에서 파이썬 임베딩 방식으로 변경
|
||||||
* 목록에서 진행률 표시 추가
|
- SJVA 시작 시 자동으로 youtube-dl 업데이트
|
||||||
|
- 목록에서 진행률 표시 추가
|
||||||
|
|
||||||
v0.1.1
|
v0.1.1
|
||||||
* 다운로드 실패 시 임시파일 삭제가 안 되는 문제 수정
|
|
||||||
|
- 다운로드 실패 시 임시파일 삭제가 안 되는 문제 수정
|
||||||
|
|
||||||
v0.1.0
|
v0.1.0
|
||||||
* 최초 공개
|
|
||||||
|
- 최초 공개
|
||||||
|
|||||||
11
info.json
11
info.json
@@ -1 +1,10 @@
|
|||||||
{"version": "3.0.1", "name": "youtube-dl", "category_name": "vod", "developer": "joyfuI", "description": "\uc720\ud29c\ube0c, \ub124\uc774\ubc84TV \ub4f1 \ub3d9\uc601\uc0c1 \uc0ac\uc774\ud2b8\uc5d0\uc11c \ub3d9\uc601\uc0c1 \ub2e4\uc6b4\ub85c\ub4dc", "home": "https://github.com/joyfuI/youtube-dl", "more": ""}
|
{
|
||||||
|
"version": "3.1.0",
|
||||||
|
"name": "youtube-dl",
|
||||||
|
"category_name": "vod",
|
||||||
|
"developer": "joyfuI",
|
||||||
|
"description": "유튜브, 네이버TV 등 동영상 사이트에서 동영상 다운로드",
|
||||||
|
"home": "https://github.com/joyfuI/youtube-dl",
|
||||||
|
"more": "",
|
||||||
|
"category": "vod"
|
||||||
|
}
|
||||||
@@ -41,14 +41,15 @@ class Status(Enum):
|
|||||||
class MyYoutubeDL(object):
|
class MyYoutubeDL(object):
|
||||||
DEFAULT_FILENAME = '%(title)s-%(id)s.%(ext)s'
|
DEFAULT_FILENAME = '%(title)s-%(id)s.%(ext)s'
|
||||||
|
|
||||||
__index = 0
|
_index = 0
|
||||||
_last_msg = ''
|
_last_msg = ''
|
||||||
|
|
||||||
def __init__(self, plugin, type_name, url, filename, temp_path, save_path=None, opts=None, dateafter=None,
|
def __init__(self, plugin, type_name, url, filename, temp_path, save_path=None, opts=None, dateafter=None,
|
||||||
datebefore=None):
|
datebefore=None):
|
||||||
# from youtube_dl.utils import DateRange
|
# from youtube_dl.utils import DateRange
|
||||||
from .plugin import youtube_dl_package
|
from .plugin import youtube_dl_package
|
||||||
DateRange = __import__('%s.utils' % youtube_dl_package, fromlist=['DateRange']).DateRange
|
DateRange = __import__('%s.utils' % youtube_dl_package, fromlist=[
|
||||||
|
'DateRange']).DateRange
|
||||||
|
|
||||||
if save_path is None:
|
if save_path is None:
|
||||||
save_path = temp_path
|
save_path = temp_path
|
||||||
@@ -67,10 +68,10 @@ class MyYoutubeDL(object):
|
|||||||
self.opts = opts
|
self.opts = opts
|
||||||
if dateafter or datebefore:
|
if dateafter or datebefore:
|
||||||
self.opts['daterange'] = DateRange(start=dateafter, end=datebefore)
|
self.opts['daterange'] = DateRange(start=dateafter, end=datebefore)
|
||||||
self.index = MyYoutubeDL.__index
|
self.index = MyYoutubeDL._index
|
||||||
MyYoutubeDL.__index += 1
|
MyYoutubeDL._index += 1
|
||||||
self.__status = Status.READY
|
self._status = Status.READY
|
||||||
self.__thread = None
|
self._thread = None
|
||||||
self.key = None
|
self.key = None
|
||||||
self.start_time = None # 시작 시간
|
self.start_time = None # 시작 시간
|
||||||
self.end_time = None # 종료 시간
|
self.end_time = None # 종료 시간
|
||||||
@@ -97,8 +98,8 @@ class MyYoutubeDL(object):
|
|||||||
def start(self):
|
def start(self):
|
||||||
if self.status != Status.READY:
|
if self.status != Status.READY:
|
||||||
return False
|
return False
|
||||||
self.__thread = Thread(target=self.run)
|
self._thread = Thread(target=self.run)
|
||||||
self.__thread.start()
|
self._thread.start()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -110,7 +111,8 @@ class MyYoutubeDL(object):
|
|||||||
self.start_time = datetime.now()
|
self.start_time = datetime.now()
|
||||||
self.status = Status.START
|
self.status = Status.START
|
||||||
# 동영상 정보 가져오기
|
# 동영상 정보 가져오기
|
||||||
info_dict = MyYoutubeDL.get_info_dict(self.url, self.opts.get('proxy'), self.opts.get('cookiefile'))
|
info_dict = MyYoutubeDL.get_info_dict(
|
||||||
|
self.url, self.opts.get('proxy'), self.opts.get('cookiefile'))
|
||||||
if info_dict is None:
|
if info_dict is None:
|
||||||
self.status = Status.ERROR
|
self.status = Status.ERROR
|
||||||
return
|
return
|
||||||
@@ -159,7 +161,8 @@ class MyYoutubeDL(object):
|
|||||||
def get_version():
|
def get_version():
|
||||||
# from youtube_dl.version import __version__
|
# from youtube_dl.version import __version__
|
||||||
from .plugin import youtube_dl_package
|
from .plugin import youtube_dl_package
|
||||||
__version__ = __import__('%s.version' % youtube_dl_package, fromlist=['__version__']).__version__
|
__version__ = __import__('%s.version' % youtube_dl_package, fromlist=[
|
||||||
|
'__version__']).__version__
|
||||||
|
|
||||||
return __version__
|
return __version__
|
||||||
|
|
||||||
@@ -171,8 +174,6 @@ class MyYoutubeDL(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
ydl_opts = {
|
ydl_opts = {
|
||||||
'simulate': True,
|
|
||||||
'dump_single_json': True,
|
|
||||||
'extract_flat': 'in_playlist',
|
'extract_flat': 'in_playlist',
|
||||||
'logger': MyLogger()
|
'logger': MyLogger()
|
||||||
}
|
}
|
||||||
@@ -181,12 +182,12 @@ class MyYoutubeDL(object):
|
|||||||
if cookiefile:
|
if cookiefile:
|
||||||
ydl_opts['cookiefile'] = cookiefile
|
ydl_opts['cookiefile'] = cookiefile
|
||||||
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
|
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
|
||||||
ydl.download([url])
|
info = ydl.extract_info(url, download=False)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Exception:%s', e)
|
logger.error('Exception:%s', e)
|
||||||
logger.error(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
return None
|
return None
|
||||||
return json.loads(MyYoutubeDL._last_msg)
|
return info
|
||||||
|
|
||||||
def my_hook(self, d):
|
def my_hook(self, d):
|
||||||
if self.status != Status.STOP:
|
if self.status != Status.STOP:
|
||||||
@@ -211,13 +212,13 @@ class MyYoutubeDL(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def status(self):
|
def status(self):
|
||||||
return self.__status
|
return self._status
|
||||||
|
|
||||||
@status.setter
|
@status.setter
|
||||||
def status(self, value):
|
def status(self, value):
|
||||||
from .plugin import socketio_emit
|
from .plugin import socketio_emit
|
||||||
|
|
||||||
self.__status = value
|
self._status = value
|
||||||
socketio_emit('status', self)
|
socketio_emit('status', self)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
68
plugin.py
68
plugin.py
@@ -23,20 +23,22 @@ youtube_dl_package = LogicNormal.get_youtube_dl_package(
|
|||||||
# 플러그인 공용
|
# 플러그인 공용
|
||||||
#########################################################
|
#########################################################
|
||||||
blueprint = Blueprint(package_name, package_name, url_prefix='/%s' % package_name,
|
blueprint = Blueprint(package_name, package_name, url_prefix='/%s' % package_name,
|
||||||
template_folder=os.path.join(os.path.dirname(__file__), 'templates'),
|
template_folder=os.path.join(
|
||||||
|
os.path.dirname(__file__), 'templates'),
|
||||||
static_folder=os.path.join(os.path.dirname(__file__), 'static'))
|
static_folder=os.path.join(os.path.dirname(__file__), 'static'))
|
||||||
|
|
||||||
menu = {
|
menu = {
|
||||||
'main': [package_name, 'youtube-dl'],
|
'main': [package_name, 'youtube-dl'],
|
||||||
'sub': [
|
'sub': [
|
||||||
['setting', '설정'], ['download', '다운로드'], ['thumbnail', '썸네일 다운로드'], ['sub', '자막 다운로드'], ['list', '목록'],
|
['setting', '설정'], ['download', '다운로드'], ['thumbnail',
|
||||||
|
'썸네일 다운로드'], ['sub', '자막 다운로드'], ['list', '목록'],
|
||||||
['log', '로그']
|
['log', '로그']
|
||||||
],
|
],
|
||||||
'category': 'vod'
|
'category': 'vod'
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin_info = {
|
plugin_info = {
|
||||||
'version': '3.0.1',
|
'version': '3.1.0',
|
||||||
'name': 'youtube-dl',
|
'name': 'youtube-dl',
|
||||||
'category_name': 'vod',
|
'category_name': 'vod',
|
||||||
'developer': 'joyfuI',
|
'developer': 'joyfuI',
|
||||||
@@ -142,8 +144,10 @@ def ajax(sub):
|
|||||||
youtube_dl = LogicNormal.download(plugin=package_name,
|
youtube_dl = LogicNormal.download(plugin=package_name,
|
||||||
url=request.form['url'],
|
url=request.form['url'],
|
||||||
filename=request.form['filename'],
|
filename=request.form['filename'],
|
||||||
temp_path=ModelSetting.get('temp_path'),
|
temp_path=ModelSetting.get(
|
||||||
save_path=ModelSetting.get('save_path'),
|
'temp_path'),
|
||||||
|
save_path=ModelSetting.get(
|
||||||
|
'save_path'),
|
||||||
format=request.form['format'],
|
format=request.form['format'],
|
||||||
preferedformat=preferedformat,
|
preferedformat=preferedformat,
|
||||||
preferredcodec=preferredcodec,
|
preferredcodec=preferredcodec,
|
||||||
@@ -158,8 +162,10 @@ def ajax(sub):
|
|||||||
youtube_dl = LogicNormal.thumbnail(plugin=package_name,
|
youtube_dl = LogicNormal.thumbnail(plugin=package_name,
|
||||||
url=request.form['url'],
|
url=request.form['url'],
|
||||||
filename=request.form['filename'],
|
filename=request.form['filename'],
|
||||||
temp_path=ModelSetting.get('temp_path'),
|
temp_path=ModelSetting.get(
|
||||||
save_path=ModelSetting.get('save_path'),
|
'temp_path'),
|
||||||
|
save_path=ModelSetting.get(
|
||||||
|
'save_path'),
|
||||||
all_thumbnails=request.form['all_thumbnails'],
|
all_thumbnails=request.form['all_thumbnails'],
|
||||||
proxy=ModelSetting.get('proxy'),
|
proxy=ModelSetting.get('proxy'),
|
||||||
ffmpeg_path=ModelSetting.get('ffmpeg_path'))
|
ffmpeg_path=ModelSetting.get('ffmpeg_path'))
|
||||||
@@ -171,8 +177,10 @@ def ajax(sub):
|
|||||||
youtube_dl = LogicNormal.sub(plugin=package_name,
|
youtube_dl = LogicNormal.sub(plugin=package_name,
|
||||||
url=request.form['url'],
|
url=request.form['url'],
|
||||||
filename=request.form['filename'],
|
filename=request.form['filename'],
|
||||||
temp_path=ModelSetting.get('temp_path'),
|
temp_path=ModelSetting.get(
|
||||||
save_path=ModelSetting.get('save_path'),
|
'temp_path'),
|
||||||
|
save_path=ModelSetting.get(
|
||||||
|
'save_path'),
|
||||||
all_subs=request.form['all_subs'],
|
all_subs=request.form['all_subs'],
|
||||||
sub_lang=request.form['sub_lang'],
|
sub_lang=request.form['sub_lang'],
|
||||||
auto_sub=request.form['auto_sub'],
|
auto_sub=request.form['auto_sub'],
|
||||||
@@ -228,7 +236,8 @@ def api(sub):
|
|||||||
return LogicNormal.abort(ret, 1) # 필수 요청 변수가 없음
|
return LogicNormal.abort(ret, 1) # 필수 요청 변수가 없음
|
||||||
if not url.startswith('http'):
|
if not url.startswith('http'):
|
||||||
return LogicNormal.abort(ret, 2) # 잘못된 동영상 주소
|
return LogicNormal.abort(ret, 2) # 잘못된 동영상 주소
|
||||||
info_dict = LogicNormal.get_info_dict(url, ModelSetting.get('proxy'))
|
info_dict = LogicNormal.get_info_dict(
|
||||||
|
url, ModelSetting.get('proxy'))
|
||||||
if info_dict is None:
|
if info_dict is None:
|
||||||
return LogicNormal.abort(ret, 10) # 실패
|
return LogicNormal.abort(ret, 10) # 실패
|
||||||
ret['info_dict'] = info_dict
|
ret['info_dict'] = info_dict
|
||||||
@@ -238,8 +247,10 @@ def api(sub):
|
|||||||
elif sub == 'download':
|
elif sub == 'download':
|
||||||
key = request.values.get('key')
|
key = request.values.get('key')
|
||||||
url = request.values.get('url')
|
url = request.values.get('url')
|
||||||
filename = request.values.get('filename', ModelSetting.get('default_filename'))
|
filename = request.values.get(
|
||||||
save_path = request.values.get('save_path', ModelSetting.get('save_path'))
|
'filename', ModelSetting.get('default_filename'))
|
||||||
|
save_path = request.values.get(
|
||||||
|
'save_path', ModelSetting.get('save_path'))
|
||||||
format_code = request.values.get('format', None)
|
format_code = request.values.get('format', None)
|
||||||
preferedformat = request.values.get('preferedformat', None)
|
preferedformat = request.values.get('preferedformat', None)
|
||||||
preferredcodec = request.values.get('preferredcodec', None)
|
preferredcodec = request.values.get('preferredcodec', None)
|
||||||
@@ -264,7 +275,8 @@ def api(sub):
|
|||||||
youtube_dl = LogicNormal.download(plugin=plugin,
|
youtube_dl = LogicNormal.download(plugin=plugin,
|
||||||
url=url,
|
url=url,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
temp_path=ModelSetting.get('temp_path'),
|
temp_path=ModelSetting.get(
|
||||||
|
'temp_path'),
|
||||||
save_path=save_path,
|
save_path=save_path,
|
||||||
format=format_code,
|
format=format_code,
|
||||||
preferedformat=preferedformat,
|
preferedformat=preferedformat,
|
||||||
@@ -274,7 +286,8 @@ def api(sub):
|
|||||||
playlist=playlist,
|
playlist=playlist,
|
||||||
archive=archive,
|
archive=archive,
|
||||||
proxy=ModelSetting.get('proxy'),
|
proxy=ModelSetting.get('proxy'),
|
||||||
ffmpeg_path=ModelSetting.get('ffmpeg_path'),
|
ffmpeg_path=ModelSetting.get(
|
||||||
|
'ffmpeg_path'),
|
||||||
key=key,
|
key=key,
|
||||||
cookiefile=cookiefile)
|
cookiefile=cookiefile)
|
||||||
if youtube_dl is None:
|
if youtube_dl is None:
|
||||||
@@ -289,8 +302,10 @@ def api(sub):
|
|||||||
elif sub == 'thumbnail':
|
elif sub == 'thumbnail':
|
||||||
key = request.values.get('key')
|
key = request.values.get('key')
|
||||||
url = request.values.get('url')
|
url = request.values.get('url')
|
||||||
filename = request.values.get('filename', ModelSetting.get('default_filename'))
|
filename = request.values.get(
|
||||||
save_path = request.values.get('save_path', ModelSetting.get('save_path'))
|
'filename', ModelSetting.get('default_filename'))
|
||||||
|
save_path = request.values.get(
|
||||||
|
'save_path', ModelSetting.get('save_path'))
|
||||||
all_thumbnails = request.values.get('all_thumbnails', False)
|
all_thumbnails = request.values.get('all_thumbnails', False)
|
||||||
dateafter = request.values.get('dateafter', None)
|
dateafter = request.values.get('dateafter', None)
|
||||||
playlist = request.values.get('playlist', None)
|
playlist = request.values.get('playlist', None)
|
||||||
@@ -310,14 +325,16 @@ def api(sub):
|
|||||||
youtube_dl = LogicNormal.thumbnail(plugin=plugin,
|
youtube_dl = LogicNormal.thumbnail(plugin=plugin,
|
||||||
url=url,
|
url=url,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
temp_path=ModelSetting.get('temp_path'),
|
temp_path=ModelSetting.get(
|
||||||
|
'temp_path'),
|
||||||
save_path=save_path,
|
save_path=save_path,
|
||||||
all_thumbnails=all_thumbnails,
|
all_thumbnails=all_thumbnails,
|
||||||
dateafter=dateafter,
|
dateafter=dateafter,
|
||||||
playlist=playlist,
|
playlist=playlist,
|
||||||
archive=archive,
|
archive=archive,
|
||||||
proxy=ModelSetting.get('proxy'),
|
proxy=ModelSetting.get('proxy'),
|
||||||
ffmpeg_path=ModelSetting.get('ffmpeg_path'),
|
ffmpeg_path=ModelSetting.get(
|
||||||
|
'ffmpeg_path'),
|
||||||
key=key,
|
key=key,
|
||||||
cookiefile=cookiefile)
|
cookiefile=cookiefile)
|
||||||
if youtube_dl is None:
|
if youtube_dl is None:
|
||||||
@@ -332,8 +349,10 @@ def api(sub):
|
|||||||
elif sub == 'sub':
|
elif sub == 'sub':
|
||||||
key = request.values.get('key')
|
key = request.values.get('key')
|
||||||
url = request.values.get('url')
|
url = request.values.get('url')
|
||||||
filename = request.values.get('filename', ModelSetting.get('default_filename'))
|
filename = request.values.get(
|
||||||
save_path = request.values.get('save_path', ModelSetting.get('save_path'))
|
'filename', ModelSetting.get('default_filename'))
|
||||||
|
save_path = request.values.get(
|
||||||
|
'save_path', ModelSetting.get('save_path'))
|
||||||
all_subs = request.values.get('all_subs', False)
|
all_subs = request.values.get('all_subs', False)
|
||||||
sub_lang = request.values.get('sub_lang', 'ko')
|
sub_lang = request.values.get('sub_lang', 'ko')
|
||||||
auto_sub = request.values.get('all_subs', False)
|
auto_sub = request.values.get('all_subs', False)
|
||||||
@@ -355,7 +374,8 @@ def api(sub):
|
|||||||
youtube_dl = LogicNormal.sub(plugin=plugin,
|
youtube_dl = LogicNormal.sub(plugin=plugin,
|
||||||
url=url,
|
url=url,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
temp_path=ModelSetting.get('temp_path'),
|
temp_path=ModelSetting.get(
|
||||||
|
'temp_path'),
|
||||||
save_path=save_path,
|
save_path=save_path,
|
||||||
all_subs=all_subs,
|
all_subs=all_subs,
|
||||||
sub_lang=sub_lang,
|
sub_lang=sub_lang,
|
||||||
@@ -364,7 +384,8 @@ def api(sub):
|
|||||||
playlist=playlist,
|
playlist=playlist,
|
||||||
archive=archive,
|
archive=archive,
|
||||||
proxy=ModelSetting.get('proxy'),
|
proxy=ModelSetting.get('proxy'),
|
||||||
ffmpeg_path=ModelSetting.get('ffmpeg_path'),
|
ffmpeg_path=ModelSetting.get(
|
||||||
|
'ffmpeg_path'),
|
||||||
key=key,
|
key=key,
|
||||||
cookiefile=cookiefile)
|
cookiefile=cookiefile)
|
||||||
if youtube_dl is None:
|
if youtube_dl is None:
|
||||||
@@ -458,4 +479,5 @@ def api(sub):
|
|||||||
# socketio
|
# socketio
|
||||||
#########################################################
|
#########################################################
|
||||||
def socketio_emit(cmd, data):
|
def socketio_emit(cmd, data):
|
||||||
socketio.emit(cmd, LogicNormal.get_data(data), namespace='/%s' % package_name, broadcast=True)
|
socketio.emit(cmd, LogicNormal.get_data(data), namespace='/%s' %
|
||||||
|
package_name, broadcast=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user