LibreELEC 설치 도중 부트 로더를 망가뜨려서 부팅 불가. Rockchip upbrick 한 결과를 정리함.
1. Board 사양

  • RK3228A, EMCP H9TQ65A8GTMCUR-KTM 2GB DDR3 + 32GB EMMC, ESP8089 2.4GHz WIFI
  • Board Version : MXQPRO_V73 2021-06-19




2. Unbrick


3. Procedure

  1. window 컴퓨터에 드라이버 및 Android Tool 을 설치함.
  2. Android Tool 을 관리자 권한으로 실행시키고, PC에 USB-A to USB-A 케이블의 한쪽을 연결함.
    • Device 연결 전이라서 "No Devices Found"



  3. MXQPRO_V73 2021-06-19는 아래 사진의 빨강 원으로 표시한 두 지점. 즉 test pin (emmc I/O)와 USB ground를 연결하여 short 내고, USB-A to USB-A 케이블의 다른 한쪽을 device(MXQ Pro 4K 5G)에 연결함.



  4.  Android Tool 을 다시 보면 device를 찾았음.
    • Device를 찾으면 두 빨강 원을 연결했던 전선을 제거해도 됨. 
    • Upgrade Firmware tab -> Firmware button으로 Rom Image 불러옴 -> Upgrade button으로 Rom Image writing.
    • 자동으로 연결이 끊겼다가 연결되었다가 하면서 Rom Image를 씀
    • [참고 site] https://en.t-firefly.com/doc/product/info/263.html




  5. 완료.

Posted by 옴팡진
,

plugin.video.daum-movie-scraper-py-1.1.0.zip
0.06MB

 

- (브니님) Kodi에 requests python modlue 설치되어야합니다. 아래 링크를 참조하여 설치 하세요. 
   [참고] https://iwf1.com/kodi/script.module.requests#google_vignette

 

Changelog

  • v1.1.0 (2021-12-31)
    • Add pasring trailer info
    • (브니님) [BugFix] Change API address http:// -> https:// 

 

Posted by 옴팡진
,

plugin.video.daum-movie-scraper-py-1.0.0.zip
0.06MB

 

- 대부분 가지고 있는 파일명 그대로 사용해도 스크래핑을 잘해옴. 
- 정말 안되면, 다음에 사이트에서 검색해보고 영화 포스터가 나오는 파일명으로 바꿈.
- 보통 "한글 영화명 (제작연도)" 의 형태가 제일 검색이 잘됨. 
       예) "벤허 (1959).mp4", "미나리 (2020).mkv" 등..

- 그래도 안되면 ".nfo" 파일을 작성함. 
- 파일명과 동일하고 확장자만 .nfo인 파일을 만들어서 파일과 동일한 디렉토리에 둠.
     예) "벤허 (1959).nfo", "미나리 (2020).nfo "  
-  파일 안에는 영화 검색에서 해당 영화의 http 주소를 넣어줌. 이중 movieId=숫자 부분을 파싱함.
    예) "https://movie.daum.net/moviedb/main?movieId=2961"(벤허, 따옴표 안에 있는 내용만 .nfo 파일에 쓰고 저장함.
- 그래도 안되는 파일명은 댓글에 남겨주시면 살펴보겠습니다. 

- 어떻게 만들었는지 관심있으신 분은 아래 링크를 참조하세요
- [ToDo List] 예고편 재생이 안됨 → 카카오티비 링크는 파싱하나 Kodi에서 실행시 별도 plugin이 필요함.

 

[개발노트] Daum Movie Scraper in Python for Kodi v19+ Matrix

(5.22)에 작성 중이라고 했는데, Kodi를 잘 안쓰다 보니 늦어지네요. ^^;; 이제는 정말로 연내 완성을 목표로 작성 중입니다. 1. Daum search page & APIs Daum Main page search : https://search.daum.net/searc..

ompanggin.tistory.com

 

Posted by 옴팡진
,

(5.22)에 작성 중이라고 했는데, Kodi를 잘 안쓰다 보니 늦어지네요. ^^;;
이제는 정말로 연내 완성을 목표로 작성 중입니다.

1. Daum search page & APIs

2. Addon Structure

  • Addon 이름
    • [addon-type].[medeia-type].[your-plugin-name] 의 형태 이름을 지여야함.
    • 대소문자를 구별하므로, 소문자로 하여야함. (Each name part is case sensitive and must be in lower case)
    • plugin.video.daum-movie-scraper-py 로함.
  • 디렉토리 구조
    • root 디렉토리에 addon.py, addon.xml 파일을 두고 다른 리소스들은 resources 에 둠.
    • addon.py
      • 메인 프로그램. 실제 실행될 python code를 작성함.
      • 이름은 마음대로 변경가능하고, 변경된 이름을 addon.xml에 정의해주어야함.
      • daum-movie-scraper.py 로함.
    • addon.xml
      • addon이 하는 일, 실행에 필요한 의존성, 실행 시작할 script 등의 kodi에게 중요한 meta data를 넘겨줌.
    • changelog.txt
      • README.md에 작성함.
    • icon.png, fanart.jpg
      • 이전 버젼에서는 root 디렉토리에 두어야 했으나, Kodi 18부터는 resource에 두고 addon.xml에서 정의함.
    • LICENSE.txt
      • GPL v3 사용
    • resources
      • root 디렉토리에 두는 파일을 제외하고 필요한 파일은 여기에 둠.
      • settings.xml
        • user-configurable setting 을 정리함.
      • icon.png
        • addon 을 나타낼때 이미지로 사용됨.
        • 256x256, 512x512 크기의 PNG 파일만 가능
        • resources/icon.png 로 하고 addon.xml 에서 <icon> 에서 위치를 지정함
      • fanart.jpg
        • addon을 사용할 때 배경화면으로 사용됨
        • 16:9, 1280x720, 1920x1080, 3840x2160 까지만 가능
        • 파일 크기는 1MB 이하로 해야하고, 가능한 최소화하여 사용함
      • language/
        • Kodi v19 Matrix 부터는 Strings.xml 대신에 Strings.po 문법에 맞춰 사용해야함.
        • 사용하는 id 번호가 정해져 있음.
          • strings 30000 thru 30999 reserved for plugins and plugin settings
          • strings 31000 thru 31999 reserved for skins
          • strings 32000 thru 32999 reserved for scripts
          • strings 33000 thru 33999 reserved for common strings used in add-ons
      • lib/
        • module 이나 3rd party software 를 둠
        • 만약, kodi.log 에서 addon.py를 찾을 수 없다고 하고, 에러가 나면 이 디렉토리에 __init__.pyo & __init__.py 가 없어서 일 수 있으므로, 다른 addon에서 copy함
      • data/
        • 필요한 static data 를 넣음
        • 당 addon에는 불필요하여 삭제
      • media/
        • 필요한 static media(picture, audio, video etc.) 를 넣음
        • 당 addon에는 불필요하여 삭제

3. test_script/scraper.py 구성

  • plugin 기능을 모사하는 test script
  1. 파일 명을 kodi로 넘겨줌
    • 스타워즈 에피소드 6: 제다이의 귀환 (더빙) (1983) (Star Wars: Episode VI - Return of the Jedi).mp4
  2. Kodi 에서 cleanTitle 을 인수로 넘겨줌
    • 제작연도와 제작연도 를 중심으로 앞 부분 title만 추출하여 "strTitleAndyear (Year).mp4" 로 리턴
    • test_script/kodi_cleanString.cpp 참조, Kodi.cleanTitleByKodi(tt)["strTitleAndYear"] 로 구현
    • 스타워즈 에피소드 6: 제다이의 귀환 (더빙) (1983).mp4
  3. movieIdInfo := self.getMovieIdInfo(strKodiTitle)
    1. strKodiTitle에 movieId 가 있으면 바로 값을 리턴
      • regExpMovieId = "movieId=(\d*)" 로 검색하여 movieId 리턴
      • 계속 잘못 찾거나 안찾아지면 Daum에서 직접 검색하여 movieId를 찾고, Kodi 재검색 대화 창에 "movieId=137137" 를 직접 입력
    2. prepTitle = self._getPrepTitle(strKodiTitle)
      • strCleanTitle = cleanTitle(strKodiTitle)
        • 더빙, 자막, 정식릴 등, 제목에 불필요한 부분을 삭제함.
        • Daum은 colon만 검색가능 : ':' (full width colon, U+FF1A ) -> ':' (colon, U+003A)로 교체
        • 스타워즈 에피소드 6: 제다이의 귀환 1983
      • 한글제목("KorTitle"), 영문제목("EngTitle"), 제작연도("year")를 갖는 딕셔너리를 리턴함.
        • prepTitle = {"KorEngTitle":"스타워즈 에피소드 6: 제다이의 귀환",
          "KorTitle":"스타워즈 에피소드 6: 제다이의 귀환", "year":"1983"}
      • 파일명의 연도는 보통 개봉연도 이나 오류도 많음.
    3. movieIdInfo := self._getMovieId(prepTitle)
      • 파일명에 연도(prepTitle.get("year")) 가 있는 경우, Daum Main 검색 (DAUM_SEARCH), Daum Movie 검색(DAUM_MOVIE_SEARCH) 순으로 검색하면서 검색 결과의 제작년도나 개봉년도가 파일의 연도와 일치할 경우에만 movieId 리턴함.
      • 파일명에 연도(prepTitle.get("year"))가 없는 경우, 일치여부 확인 안함. Daum Main 검색에서는 검색되는 결과로, Daum Movie 검색에서는 첫번째 결과를 리턴함.
      • 검색순서 1) Daum Main 검색에서 "한글+연도" 키워드로, 2) Daum Main 검색에서 "한글" 키워드로 검색, 3) Daum Movie 검색에서 "한글+연도", 4) Daum Movie 검색에서 "한글" 키워드로 검색, 5) year 제외(prepTitle.pop("year") )하고 다시 1) ~ 4) 순 검색
      • prepTitle["searchKeyword"]
        • 검색할 키워드를 작성함. Daum Main 검색은 연도를 쓰는 것이, Daum Movie 검색은 연도를 안쓰는 것이 검색이 잘됨
        • 한글 영화명이 있으면 한글 영화명 우선으로 "korTitle" + " " + "year" 형태로 키워드 작성함.
          예) "스타워즈 에피소드 6: 제다이의 귀환 1983"
      • 검색 결과의 data형 확인, 동일 data형으로 변환하여 사용.
        예) Daum Movie page API의 productionYear는 <class 'int'>, movieId = <class 'str'>
  4. rlt := self.getMovieInfo(movieId=movieId)
    • DAUM_API_MAIN 에서 리턴한 string을 json 로드하여 규칙에 맞게 처리함.
    • 입력은 rltAPI = json.load(DAUM_API_MAIN의 검색결과) 또는 movieId=movieId 로 가능
    • Daum Movie 검색시에 관련된 모든 영화가 리스트되고, 리스트된 영화는 모두 parsing해야하므로,
      유명하지 않은 영화들의 정보를 기준으로 item 들을 처리하여함.
      예) "명당" movieId=111569 검색시, "감투봉 명당 싸움" movieId=52625 도 리스트되므로 처리필요
    • 검색 실패해도 프로그램 중지되지 않도록 예외처리 필요함.
  5. rlt := self.getCastInfo(movieId=movieId)
    • DAUM_API_MAIN 에서 리턴한 string을 json 로드하여 규칙에 맞게 처리함.
    • 입력은 rltAPI = json.load(DAUM_API_MAIN의 검색결과) 또는 movieId=movieId 로 가능
    • castInfo["role"]은 배역명 apiCast["description"]을 쓰고 없으면 주연, 출연 등의 역할 apiCast["movieJob"]["role"] 을 사용
  6. rlt := self.getMainPosterInfo(movieId=movieId)
    • DAUM_API_MAIN 에서 리턴한 string을 json 로드하여 규칙에 맞게 처리함.
    • 입력은 rltAPI = json.load(DAUM_API_MAIN의 검색결과) 또는 movieId=movieId 로 가능
    • Poster Thumbnail은 C408x596 사용
  7. rlt := self.getPhotoInfo(movieId=movieId)
    • DAUM_API_PHOTO 에서 리턴한 string을 json 로드하여 규칙에 맞게 처리함.
    • 입력은 rltAPI = json.load(DAUM_API_PHOTO의 검색결과) 또는 movieId=movieId 로 가능
    • photoList?page=1&size={size}&adultFlag=T 에서 sz=1로 호출 후 sz=totalElements 로 할당 후 재호출
    • movieCategory 가 "스틸", "포스터","촬영 현장", "행사" 순으로 나옴
      • 포스터는 포스터에 저장하고, 나머지는 fanart로 저장함
    • 저장하는 최대 포스터 및 fanart 갯수는 resources/settings.xml 에서 정함.
    • 원본 url 을 주면 thumnail로 바꿔주나, size는 정해져 있음. 아무숫자나 쓰면 페이지 못찾음.
      • 포스터는 C408x596, 스틸은 S408x212 로하려 했으나, 원본의 종횡비가 다를 경우 이미지 잘림
      • 포스터는 유지 C408x596, 스틸은 C314x0 으로 함.
  8. rlt := self.getTrailerInfo(movieId=movieId)

4. daum-movie-scraper.py

  • Kodistubs : https://romanvm.github.io/Kodistubs/index.html
    • IDE 상에서 kodi 함수를 autocompletion이 되도록 최소한의 함수 모음.
  • Kodi <--> Scraper Flow chart
    1. [Kodi] action=find
      • Kodi에서 파일명을 검색하여 ('plugin path', 'handle', 'query', 'rsume')
        2021-12-05 21:22:12.382 T:64864 DEBUG <general>: StartScript - calling plugin The Movie Database Python('plugin://metadata.themoviedb.org.python/','1','?action=find&pathSettings=%7b%22RatingS%22%3a%22TMDb%22%2c%22add_tags%22%3atrue%2c%22certprefix%22%3a%22Rated%20%22%2c%22enable_fanarttv_artwork%22%3atrue%2c%22fanart%22%3atrue%2c%22fanarttv_clientkey%22%3a%22%22%2c%22fanarttv_language%22%3a%22en%22%2c%22imdbanyway%22%3afalse%2c%22keeporiginaltitle%22%3afalse%2c%22landscape%22%3atrue%2c%22language%22%3a%22en-US%22%2c%22lastUpdated%22%3a%220%22%2c%22multiple_studios%22%3afalse%2c%22originalUrl%22%3a%22%22%2c%22previewUrl%22%3a%22%22%2c%22tmdbcertcountry%22%3a%22us%22%2c%22trailer%22%3atrue%2c%22traktanyway%22%3afalse%7d&title=%eb%af%b8%eb%82%98%eb%a6%ac&year=2020','resume:false')​
      • decode 하면
        2021-12-0521:22:12.382T:64864DEBUG<general>:StartScript-callingpluginTheMovieDatabasePython('plugin://metadata.themoviedb.org.python/','1','?action=find&pathSettings={"RatingS":"TMDb","add_tags":true,"certprefix":"Rated ","enable_fanarttv_artwork":true,"fanart":true,"fanarttv_clientkey":"","fanarttv_language":"en","imdbanyway":false,"keeporiginaltitle":false,"landscape":true,"language":"en-US","lastUpdated":"0","multiple_studios":false,"originalUrl":"","previewUrl":"","tmdbcertcountry":"us","trailer":true,"traktanyway":false}&title=미나리&year=2020','resume:false')​
      • query
        • action : plugin 이 처리해야할 내용 전달,
          • find : 영화를 구별할 수 있는 uniqueids 를 확보 후 기록하여야함
          • getdetails : movie info를 확보하여 기록함.
        • pathSettings : resources/settings.xml 에 있는 id 값을 전달함.
        • title, year : 파일이름으로 title과 year를 파싱하여 전달함. year는 파일에 따라서 없을 수도 있음.
      • query 중 {title=미나리&year=2020 활용} 하여 movieId 찾고 uniqueids를 저장할 것을 지시함.
    2. [Plugin] uniqueids
      • 입력받은 query 로 부터 영화를 구별할 수 있는 uniqueids를 저장함.
      • 보통 movieId 를 사용함. 예) TMDB scraper는 {"tmdb": "615643"}
      • 전달받은 query 중, title, year 을 활용하여 movieId를 찾아서 uniqueids를 저장함.
        • year는 파일에 따라서 없을 수도 있음.
        • 미나리는 uniqueids= {"daum": "137317"} 로 저장함.
    3. [Kodi] action=getdetails
      • ('plugin path', 'handle', 'query', 'rsume')
        2021-12-05 21:22:15.058 T:64864 DEBUG <general>: StartScript - calling plugin The Movie Database Python('plugin://metadata.themoviedb.org.python/','1','?action=getdetails&url=%7b%22tmdb%22%3a%20%22615643%22%7d&pathSettings=%7b%22RatingS%22%3a%22TMDb%22%2c%22add_tags%22%3atrue%2c%22certprefix%22%3a%22Rated%20%22%2c%22enable_fanarttv_artwork%22%3atrue%2c%22fanart%22%3atrue%2c%22fanarttv_clientkey%22%3a%22%22%2c%22fanarttv_language%22%3a%22en%22%2c%22imdbanyway%22%3afalse%2c%22keeporiginaltitle%22%3afalse%2c%22landscape%22%3atrue%2c%22language%22%3a%22en-US%22%2c%22lastUpdated%22%3a%220%22%2c%22multiple_studios%22%3afalse%2c%22originalUrl%22%3a%22%22%2c%22previewUrl%22%3a%22%22%2c%22tmdbcertcountry%22%3a%22us%22%2c%22trailer%22%3atrue%2c%22traktanyway%22%3afalse%7d','resume:false')​
         
      • decode하면,
        2021-12-0521:22:15.058T:64864DEBUG<general>:StartScript-callingpluginTheMovieDatabasePython('plugin://metadata.themoviedb.org.python/','1','?action=getdetails&url={"tmdb": "615643"}&pathSettings={"RatingS":"TMDb","add_tags":true,"certprefix":"Rated ","enable_fanarttv_artwork":true,"fanart":true,"fanarttv_clientkey":"","fanarttv_language":"en","imdbanyway":false,"keeporiginaltitle":false,"landscape":true,"language":"en-US","lastUpdated":"0","multiple_studios":false,"originalUrl":"","previewUrl":"","tmdbcertcountry":"us","trailer":true,"traktanyway":false}','resume:false')​
      • query 중 url={"tmdb": "615643"} 로 활용 하여 movieInfo를 가져올 것을 지시함.
    4. [Plugin] movieInfos : uniqueids 를 이용하여 movie info를 scrapping 하고 저장
      • 전달받은 query 중, url={"tmdb": "615643"}을 활용하여 Daum에서 scraping 하여 movieInfo저장
    5. [Kodi] action =NfoUrl : nfo 파일처리
      • ('plugin path', 'handle', 'query', 'rsume')
        2021-12-15 00:50:52.655 T:1397176 DEBUG <general>: StartScript - calling plugin The Movie Database Python('plugin://metadata.themoviedb.org.python/','1','?action=NfoUrl&nfo=https%3a%2f%2fwww.themoviedb.org%2fmovie%2f615643-minari%3flanguage%3dko%0a&pathSettings=%7b%22RatingS%22%3a%22TMDb%22%2c%22add_tags%22%3atrue%2c%22certprefix%22%3a%22Rated%20%22%2c%22enable_fanarttv_artwork%22%3atrue%2c%22fanart%22%3atrue%2c%22fanarttv_clientkey%22%3a%22%22%2c%22fanarttv_language%22%3a%22en%22%2c%22imdbanyway%22%3afalse%2c%22keeporiginaltitle%22%3afalse%2c%22landscape%22%3atrue%2c%22language%22%3a%22en-US%22%2c%22lastUpdated%22%3a%220%22%2c%22multiple_studios%22%3afalse%2c%22originalUrl%22%3a%22%22%2c%22previewUrl%22%3a%22%22%2c%22tmdbcertcountry%22%3a%22us%22%2c%22trailer%22%3atrue%2c%22traktanyway%22%3afalse%7d','resume:false')​
      • decode하면,
        2021-12-15 00:50:52.655 T:1397176 DEBUG <general>: StartScript - calling plugin The Movie Database Python('plugin://metadata.themoviedb.org.python/','1','?action=NfoUrl&nfo=https://www.themoviedb.org/movie/615643-minari?language=ko &pathSettings={"RatingS":"TMDb","add_tags":true,"certprefix":"Rated ","enable_fanarttv_artwork":true,"fanart":true,"fanarttv_clientkey":"","fanarttv_language":"en","imdbanyway":false,"keeporiginaltitle":false,"landscape":true,"language":"en-US","lastUpdated":"0","multiple_studios":false,"originalUrl":"","previewUrl":"","tmdbcertcountry":"us","trailer":true,"traktanyway":false}','resume:false')​
      • nfo = "파일이름과_동일.nfo" 파일을 읽어서 내용을 리턴함.
        • nfo 내용을 파싱해서 uniqueids 를 저장함. 이후 action=getdetails 순으로 진행됨.
        • 파일별로 별도의 디렉토리를 만들고, movie.nfo 로 써도 nfo 파일로 인식함.
        • https://movie.daum.net/moviedb/main?movieId=137317 를 nfo 파일에 넣고, movieId를 파싱함.
  • TrailInfo
    • DAUM_API_VIDEO = "http://movie.daum.net/api/video/list/movie/{movieId}?page=1&size=20"
      • 동영상 리스트를 확보하여 subtilte에 "메인 예고, 공식 예고, 본 예고, 티저 예고, 1차, 2차 예고" 등이 있는 첫번째 traiier의 linkId를 찾음.
    • DAUM_API_TRAILER_INFO = "https://play-tv.kakao.com/api/v1/ft/playmeta/cliplink/{linkId}?fileds=@html5vod&service=und_player&type=VOD" 의 "videoOutputList" 에서 가용한 예고편의 해상도가 있음.
      • (Mode : 해상도) HIGH4 :1080p 1920x1080, HIGH : 720p1280x720, MAIN: 480p 854x480, BASE : 360p 640x360, LOW : 240p 426x240, AUDIO 0x0 로 구성되어 있음
      • 가용한 해상도를 구하고, HIGH 720p가 있을 이를 default로 사용함. 없으면 MAIN,BASE, LOW 순으로.
    • DAUM_API_TRAILER_PLAYABLE_URL = "https://play-tv.kakao.com/katz/v3/ft/cliplink/{linkId}/readyNplay?player=monet_html5&uuid=3244cf0161c250497bcf962be670fad0&profile={mode}&service=und_player&section=und_player&fields=seekUrl,abrVideoLocationList&playerVersion=3.11.14&appVersion=96.0.4664.110&startPosition=0&tid=&dteType=PC&continuousPlay=false&autoPlay=false&contentType=&drmType=widevine&ab=&literalList=&1640124549976"
      • linkId 와 mode 를 입력으로하여 playable trailer url을 찾아냄.
  •  Debugging
    • 한글처리에서 6시간 넘게 고생함.
    • mac용이어서 인지 모르겠는데, 한글을 자소를 분리한 형태로 다루고 보여줄 때만 모아서 보여줌.
    • Kodi 에서 보내주는 한글이 자소가 분리되어 있어서 정규식으로 검출이 안되고, daum에서도 검색이 안됨.
    • [참고] https://jonsyou.tistory.com/26
    • Kodi에서 넘겨준 파라미터를 받을 때 자소를 모아서 처리함.
      • prepQuery = unicodedata.normalize("NFC", query)

5. 이전 버전에서 update 필요사항

  • Blog 내 댓글에서 반영이 필요한 파일 리스트 정리 -> 반영확인 완료
  • 예고편 에러 -> kakao TV 링크로 반영완료
    titleList = [
        # Blue 2020.02.05
        # ':' 부분을 kodi에서는 UTF8로 %ef%bc%9a 로 처리하는데 daum 은 %3a로 해야 인식
        # "한글+숫자+한글" 에서 숫자 누락
        """스타워즈 에피소드 6: 제다이의 귀환 (1983)_(Star Wars: Episode VI - Return of the Jedi)""",
        """스타워즈: 깨어난 포스 (2015)_(Star Wars: The Force Awakens)""",
    
        # 아마도 2020.04.23,  :, !를 인식하지 못함.
        """짱구는 못말려 극장판:엄청 맛있어! B급 음식 서바이벌! (2013)""",
    
        # Murian 2020.04.23, 라이브러리에서 예고편을 선택하면 스킨이 강제종료
        # 로그를 보면 이런 에러가 뜹니다.
        # 2020-04-23 13:48:45.987 T:4928 ERROR: ffmpeg[1340]: [tcp] Failed to resolve hostname
        # mmc.daumcast.net: Temporary failure in name resolution
        # Daum에서 예고편 영상을 daumcast에서 kakao TV 로 옮겼는데, 검색결과는 그대로 daumcast 로함.
    
        # 아마도 2020.04.27
        # 다음영화에서 검색하면 제작연도가 개봉연도와 표기된 연도가 달라서 불러오지 못한 것이었습니다.  
        # 제작년도와 개봉년도가 다르면 제작년도를 써야함.
        """마스크(1994)""",
        """겨울왕국(2013)""",
        """겨울왕국2(2019)""",
        """첫 키스만 50번째(2004)""",
        """심야식당(2014)""",
    
        # 책상물림 2020.05.28
        # 중간에 '-' 등의 처리
        """탐정 - 더 비기닝(2015)""",
        """탐정 - 리턴즈(2018)""",
        """엽문1""",
        """엽문2"""
    ]​

6. Kodi source 참조

  • Kodi 파일명을 정리하여 "제목(연도)" 형태로 보냄
    // https://github.com/xbmc/xbmc/blob/master/xbmc/settings/AdvancedSettings.cpp
    // m_videoCleanDateTimeRegExp = "(.*[^ _\\,\\.\\(\\)\\[\\]\\-])[ _\\.\\(\\)\\[\\]\\-]+(19[0-9][0-9]|20[0-9][0-9])([ _\\,\\.\\(\\)\\[\\]\\-]|[^0-9]$)?";
    
    // m_videoCleanStringRegExps.clear();
    // m_videoCleanStringRegExps.emplace_back("[ _\\,\\.\\(\\)\\[\\]\\-](aka|ac3|dts|custom|dc|remastered|divx|divx5|dsr|dsrip|dutch|dvd|dvd5|dvd9|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|extended|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|3d|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|cd[1-9]|\\[.*\\])([ _\\,\\.\\(\\)\\[\\]\\-]|$)");
    // m_videoCleanStringRegExps.emplace_back("(\\[.*\\])");
    
    // for web : 
    // (.*[^  _\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9][0-9]|20[0-9][0-9])([ _\,\.\(\)\[\]\-]|[^0-9]$)?
    // [ _\,\.\(\)\[\]\-](aka|ac3|dts|custom|dc|remastered|divx|divx5|dsr|dsrip|dutch|dvd|dvd5|dvd9|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|extended|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|3d|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|cd[1-9]|\[.*\])([ _\,\.\(\)\[\]\-]|$)
    // (\[.*\])
    
    // https://github.com/xbmc/xbmc/blob/master/xbmc/Util.cpp
    
    void CUtil::CleanString(const std::string& strFileName,
                            std::string& strTitle,
                            std::string& strTitleAndYear,
                            std::string& strYear,
                            bool bRemoveExtension /* = false */,
                            bool bCleanChars /* = true */)
    {
    
    // return strTitle, strTitleAndYear, strYear
    // 1) strTitleAndYear = "중경삼림.Chungking.Express.1994.Criterion.BluRay.1080p.x265.10bit.AAC-highcal.mkv"
    // 2) strTitleAndYear = "가구야공주_이야기_1080p_한글자막.mkv"
    // 3) strTitleAndYear = "발레리나 이야기.mp4"
    
      strTitleAndYear = strFileName; 
    
      if (strFileName == "..")
       return;
    
      const std::shared_ptr<CAdvancedSettings> advancedSettings = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings();
      const std::vector<std::string> &regexps = advancedSettings->m_videoCleanStringRegExps;
    
      // https://github.com/xbmc/xbmc/blob/master/xbmc/utils/RegExp.cpp
      CRegExp reTags(true, CRegExp::autoUtf8);  // true ; case sensitive
      CRegExp reYear(false, CRegExp::autoUtf8);
    
    // regex compile 해서 private PCRE::pcre* m_re; 에 저장
    // m_videoCleanDateTimeRegExp = "(.*[^ _\\,\\.\\(\\)\\[\\]\\-])[ _\\.\\(\\)\\[\\]\\-]+(19[0-9][0-9]|20[0-9][0-9])([ _\\,\\.\\(\\)\\[\\]\\-]|[^0-9]$)?";
    
      if (!reYear.RegComp(advancedSettings->m_videoCleanDateTimeRegExp))
      {
        CLog::Log(LOGERROR, "{}: Invalid datetime clean RegExp:'{}'", __FUNCTION__,
                  advancedSettings->m_videoCleanDateTimeRegExp);
      }
      else
      {
    
        if (reYear.RegFind(strTitleAndYear.c_str()) >= 0)
        {
          strTitleAndYear = reYear.GetMatch(1);
          strYear = reYear.GetMatch(2);
        }
      }
    
      // 1) strTitleAndYear = "중경삼림.Chungking.Express", strYear = "1994" 
      // 2) strTitleAndYear = "가구야공주_이야기_1080p_한글자막.mkv"
      // 3) strTitleAndYear = "발레리나 이야기.mp4"
    
      URIUtils::RemoveExtension(strTitleAndYear);
    
      // 1) strTitleAndYear = "중경삼림.Chungking.Express", strYear = "1994" 
      // 2) strTitleAndYear = "가구야공주_이야기_1080p_한글자막"
      // 3) strTitleAndYear = "발레리나 이야기"
    
    // m_videoCleanStringRegExps.emplace_back("[ _\\,\\.\\(\\)\\[\\]\\-](aka|ac3|dts|custom|dc|remastered|divx|divx5|dsr|dsrip|dutch|dvd|dvd5|dvd9|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|extended|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|3d|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|cd[1-9]|\\[.*\\])([ _\\,\\.\\(\\)\\[\\]\\-]|$)");
    // m_videoCleanStringRegExps.emplace_back("(\\[.*\\])");
    
      for (const auto &regexp : regexps)
      {
        if (!reTags.RegComp(regexp.c_str()))
        { // invalid regexp - complain in logs
          CLog::Log(LOGERROR, "{}: Invalid string clean RegExp:'{}'", __FUNCTION__, regexp);
          continue;
        }
        int j=0;
        if ((j=reTags.RegFind(strTitleAndYear.c_str())) > 0)
          strTitleAndYear = strTitleAndYear.substr(0, j); // 앞부터 찾은 위치까지 return 함. "_1080p_" 찾음.
      }
    
      // 1) strTitleAndYear = "중경삼림.Chungking.Express", strYear = "1994" 
      // 2) strTitleAndYear = "가구야공주_이야기"
      // 3) strTitleAndYear = "발레리나 이야기"
    
      // final cleanup - special characters used instead of spaces:
      // all '_' tokens should be replaced by spaces
      // if the file contains no spaces, all '.' tokens should be replaced by
      // spaces - one possibility of a mistake here could be something like:
      // "Dr..StrangeLove" - hopefully no one would have anything like this.
    
      if (bCleanChars)
      {
        bool initialDots = true;
        bool alreadyContainsSpace = (strTitleAndYear.find(' ') != std::string::npos);
    
        for (char &c : strTitleAndYear)
        {
          if (c != '.')
            initialDots = false;
    
          if ((c == '_') || ((!alreadyContainsSpace) && !initialDots && (c == '.'))) // "_" 이거나, " "가 없고, 처음이 아닌 "."이면 " "로 바꿈
          {
            c = ' ';
          }
        }
      }
    
      // 1) strTitleAndYear = "중경삼림 Chungking Express", strYear = "1994" 
      // 2) strTitleAndYear = "가구야공주 이야기"
      // 3) strTitleAndYear = "발레리나 이야기"
    
      StringUtils::Trim(strTitleAndYear);
      strTitle = strTitleAndYear;
    
      // 1) strTitle = "중경삼림 Chungking Express", strTitleAndYear = "중경삼림.Chungking.Express", strYear = "1994" 
      // 2) strTitle = "가구야공주 이야기", strTitleAndYear = "가구야공주 이야기"
      // 3) strTitle = "발레리나 이야기", strTitleAndYear = "발레리나 이야기"
    
      // append year
      if (!strYear.empty())
        strTitleAndYear = strTitle + " (" + strYear + ")";
    
      // 1) strTitle = "중경삼림 Chungking Express", strTitleAndYear = "중경삼림.Chungking.Express(1994)", strYear = "1994" 
      // 2) strTitle = "가구야공주 이야기", strTitleAndYear = "가구야공주 이야기"
      // 3) strTitle = "발레리나 이야기", strTitleAndYear = "발레리나 이야기"
    
      // restore extension if needed
      if (!bRemoveExtension)
        strTitleAndYear += URIUtils::GetExtension(strFileName);
    }
    
    // https://github.com/xbmc/xbmc/blob/master/xbmc/utils/URIUtils.cpp
    
    void URIUtils::RemoveExtension(std::string& strFileName)
    {
      if(IsURL(strFileName))
      {
        CURL url(strFileName);
        strFileName = url.GetFileName();
        RemoveExtension(strFileName);
        url.SetFileName(strFileName);
        strFileName = url.Get();
        return;
      }
    
      // strFileName = "가구야공주_이야기_1080p_한글자막.mkv"
      size_t period = strFileName.find_last_of("./\\");  // 마지막에 있는 ".", "/", "\"의 위치를 찾는다.
    
      if (period != std::string::npos && strFileName[period] == '.')    // 마지막에 찾은 위치의 글자가 "." 이면
      {
        //   basic_string substr(size_type pos = 0, size_type count = npos) const; 
        // pos 부터 npos 개 만큼 return, npos 가 없으면 끝까지 return
        std::string strExtension = strFileName.substr(period); // "." 부터 끝까지 return ".mkv"
        StringUtils::ToLower(strExtension); // 소문자로 ".mkv"
        strExtension += "|";    // ".mkv|"
    
        std::string strFileMask;
        strFileMask = CServiceBroker::GetFileExtensionProvider().GetPictureExtensions();
        strFileMask += "|" + CServiceBroker::GetFileExtensionProvider().GetMusicExtensions();
        strFileMask += "|" + CServiceBroker::GetFileExtensionProvider().GetVideoExtensions();
        strFileMask += "|" + CServiceBroker::GetFileExtensionProvider().GetSubtitleExtensions();
    #if defined(TARGET_DARWIN)
        strFileMask += "|.py|.xml|.milk|.xbt|.cdg|.app|.applescript|.workflow";
    #else
        strFileMask += "|.py|.xml|.milk|.xbt|.cdg";
    #endif
        strFileMask += "|";
    
        // picture, music, video, subtitle extenstion이면 지움
        if (strFileMask.find(strExtension) != std::string::npos)
          strFileName.erase(period); // "."부터 끝까지 지움.// strFileName = "가구야공주_이야기_1080p_한글자막"
      }
    }
    
    std::string URIUtils::GetExtension(const std::string& strFileName)
    {
      if (IsURL(strFileName))
      {
        CURL url(strFileName);
        return GetExtension(url.GetFileName());
      }
    
      size_t period = strFileName.find_last_of("./\\");
      if (period == std::string::npos || strFileName[period] != '.')
        return std::string();   // ".", "\","/"이 없거나, 마지막 찾은 것이 "." 이 아니면 빈 string return
    
      return strFileName.substr(period);    // "."이 있으면 "."부터끝까지 ".mkv"
    }​
Posted by 옴팡진
,

기존 사용 중이던 S905의  smb 속도가 내부 emmc에서는 정상이나, USB  외장 HDD에서는 1MB/s 수준으로 사용이 어려움.  USB port 고장으로 판단하고 신규 구입함.

처음 주문한 것은 Tanix TX3 mini 로 Armlogic S905W, eMMC 16GB+ DDR3 2GB 인데, 들어있는 것은 Rockchip  rk3228A, eMCP 8GB + DDR3 1GB 로 fake 제품.

MXQ Pro 4K 5G 내장 메모리 32GB, 램 2GB 을 신규 구입 ($21)


 

1. MXQ Pro 4K 5G

  • Box Open 후 IC 확인
  • RK3228A, EMCP H9TQ65A8GTMCUR-KTM 2GB DDR3 + 32GB EMMC, ESP8089 2.4GHz WIFI
  • H/W Info : http://ix.io/3zit

 

2. 설치 방법

 

A. Multitool

  • Image Download : https://drive.google.com/file/d/1fpPwxuVa-T-utWBBwDvU6R-jaX2AlcqT/view?usp=sharing 
  • 압축해제 
: xz 압축율이 좋아서 많이 사용. 단일파일만 가능하여 tar와 연계하여 사용
    xz multitool.img.xz​
  • SD 카드에 이미지 씀 (mac command line interface)

    sudo diskutil list 	#SD card dev 확인 /dev/disk2

    sudo diskutil umountDisk /dev/disk2  #SD 카드를 풀어줌

    sudo dd bs=1m if=./multitool.img of=/dev/rdisk2;sync #disk2아님. rdisk2(raw disk)​​
  • SD card를 넣고 전원 인가
    • Multitool이 처음 부팅시 armbian image를 넣는 fat32 partition 을 resize하여 시간이 오래 걸림.
    • 내부 flash backup 함 (option). 완료되면 내부 flash를 삭제함. SD card 로 부팅할수 있게 됨

 

B.  SD card에 Armbian 설치하여 정상작동 확인

  • Image Download : https://redirect.armbian.com/rk322x-box/Focal_current_xfce
    • Armbian forum에 image 에는 RK322x DTB 파일이 없어서 설치 불가

    • 위의 전용 Armbian image 사용
  • 압축해제 
: xz 압축율이 좋아서 많이 사용. 단일파일만 가능하여 tar와 연계하여 사용
 
     xz Armbian_21.08.1_Rk322x-box_focal_current_5.10.60_xfce_desktop.img.xz​
  • SD card에 이미지 씀 (mac command line interface)
    sudo diskutil list 	#SD card dev 확인, 예, /dev/disk2

    sudo diskutil umountDisk /dev/disk2 	#SD 카드를 풀어줌

    sudo dd bs=1m if=./Armbian_21.08.1_Rk322x-box_focal_current_5.10.60_xfce_desktop.img of=/dev/rdisk2;sync 	#disk2아님 rdisk2(raw disk)​
  • SD card를 넣어 정상 작동하는 지 확인함. 

    • 파란색 LED가 깜빡이면 부팅 중.  시작까지 좀 시간이 걸리므로 최대 10분까지 대기. 

    • 작동에 이상이 있으면 , sudo armbianmonitor -u 해서 hw-info를 forum에 올리고 수정된 image에 대한 도움을 요청.
    •  MXQ Box HW-INFO : http://ix.io/3zit

 

C. 내부 저장소에 Armbian 설치

  • Multitool 내부 images/ 에 Armbian image를 옮김
. 압축 상태의 image 파일을 옮겨도 됨.
    mv Armbian_21.08.1_Rk322x-box_focal_current_5.10.60_xfce_desktop.img.xz /Volumes/MULTITOOL/images/​

    • File system이 vfat으로 되어 있어서 단일 파일의 크기가 4GB 이상은 쓰기 불가
  -> 압축해제하고 옮기면 -> write failed: File too large 로 옮길 수 없음


  • Burn image to flash (usually mmcblk2)

    • SD card를 넣고 부팅하여 Burn image to flash (usually mmcblk2) 선택

    • 설치가 완료되면 shutdown 하고 전원 제거 후 SD card 제거

  • 재부팅하면 자동으로 잔여 설치가 진행되고, root password, adduser 등을 수행함
    • default login 으로 xfce GUI login 으로 설정되어 있음. 


 

3. 서버 설정

[참고] https://ompanggin.tistory.com/15?category=575270

 

A. GUI login disable 

 

B. locale 설정

 

C. time zone 설정 

  • 
기본으로 설정되나 안되면 아래 확인해서 설정
    sudo /usr/bin/timedatectl set-timezone Asia/Seoul​

 

D. fstab 설정

  • https://hanseokhyeon.tistory.com/entry/우분투에서-하드디스크-자동-마운트하기
    
    sudo vi /etc/fstab
    
    아래 내용 끝 줄에 추가
    UUID="e1a285c7-7f6b-4b2d-9e6f-056bbd3b9d35" /common     ext3 defaults,nofail,x-systemd.device-timeout=30 0 0​


  • HDD idle time 설정, shell-script 작성하여 부팅시 실행

    vi AfterBoot.sh
    
    아래 내용 신규 작성
    #!/bin/sh -e 
    HDD_ID='/dev/disk/by-uuid/e1a285c7-7f6b-4b2d-9e6f-056bbd3b9d35'
    
    if [ -e $HDD_ID ]
    then
            sudo /sbin/hdparm -B 127 -S 200 $HDD_ID
    else
            /bin/echo "HDD is not mounted." 
    fi​

 

E. 사용자 실행파일 path 설정

  • .bashrc에 bin 디렉토리 추가 
    vi $HOME/.bashrc
    
    아래 내용 끝 줄에 추가
    export $PATH=$PATH:$HOME/bin​

 

F. EBS 녹음 설정

  • 
ffmpeg 설치
    sudo apt-get install ffmpeg​
  •  baidu 백업용 python module 설치  
    sudo pip install bypy​
  •  EBS 녹음 script 작성 및 crontab 등록
  [참고] https://ompanggin.tistory.com/31 

 

G. transmission 설치


  • 설치
    sudo apt-get install transmission-daemon transmission-cli​
  • 서비스 멈추고 설정 해야함. 종료시 설정파일을 기존 파일로 덮어씀.
    
    sudo service transmission-daemon stop 
    
    sudo vi /etc/transmission-daemon/settings.json​
  • ~/.config/transmission-daemon/settings.json 을 두고 /etc/transmission-daemon/settings.json 에 link 함.
    backup 용이. .config 통째로 옮김.

  • 설정파일 항목 참조 : https://oslinux.tistory.com/9 , https://github.com/transmission/transmission/wiki/Editing-Configuration-Files 
 
  • 실행계정 변경 
   아래 2개의 데몬 파일 내의 User항목을 변경하고, 관련 파일의 소유권을 변경
          
    USER=debian-transmission -> USER=kodi

    /etc/systemd/system/multi-user.target.wants/transmission-daemon.service  
          
    /etc/init.d/transmission-daemon​

    
         
  • [참고] http://yellowtopaz.tistory.com/195, http://m.blog.naver.com/garyang/220395326728, 

 

H. samba 설정


 

I. rsync 설정


  • [참고] https://serverspace.io/support/help/use-rsync-to-create-a-backup-on-ubuntu/
  • 서버에 rsync 설정하면, android 기기에서 쉽게 파일을 옮길 수 있음.

    sudo ln -s /lib/systemd/system/rsync.service /etc/systemd/system/rsync.service

    
    sudo vi /etc/rsyncd.conf
   
    
    예시, 아래 내용 추가
    uid = kodi
   
    gid = kodi
   
    use chroot = yes
   
    max connections = 4
   
    read only = false
   
    syslog facility = local5
   
    pid file = /var/run/rsyncd.pid

   
    
    [Download]
      
       path = /common/Downloads/
      
       comment = Downloads Directory
   
    [Music]
       
       path = /common/Musics/karlken/
       
       comment = Karlken Music directory​
      
  • ~/.config/rsync/rsyncd.conf 를 만들고 /etc/rsyncd.conf에 링크하면 백업 용이함. 

 

Posted by 옴팡진
,

1. Upgrade To Ubuntu LTS 20.04 Focal FossA

0) Armbian  Forum Link
      : https://forum.armbian.com/topic/12162-single-armbian-image-for-rk-aml-aw-aarch64-armv8/

1) 이미지 다운로드
      : Ubuntu 20.04.2.0 LTS (Focal Fossa) 
      : https://users.armbian.com/balbes150/arm-64/Armbian_20.10_Arm-64_focal_current_5.9.0.img.xz

2) 압축해제
      : xz
압축율이 좋아서 많이 사용. 단일파일만 가능하여 tar 연계하여 사용
        xz Armbian_20.10_Arm-64_focal_current_5.9.0.img.xz

3) SD 카드에 이미지 (mac command line interface)
      : diskutil list (SD card dev 확인, , /dev/disk2)  
      : diskutil umountDisk /dev/disk2 (SD
카드를 풀어줌)
      : udo dd bs=1m if=./Armbian_20.10_Arm-64_focal_current_5.9.0.img of=/dev/rdisk2;sync
       (
이미지씀. disk2 아닌 rdisk2(raw disk) 5GB 오래걸림 11851s(?))
       [
참고] https://www.raspberrypi.org/documentation/installation/installing-images/mac.md
      [block size] bs=1m, 726958 byte/sec  2시간 정도
      default 512k , 167379byte/sec, bs=8m
일때 743748 byte/sec

4) Boot
      : /dtb/amlogic/meson-gxbb-p200.dtb 설정
      :
이쑤시개로  reset 버튼을 누른 상태로 전원 연결
      : Alert! LABEL=Rootfs does not exists
에러로 부팅 불가
       -> DTB
SD Card 인식을 못해서   (This means that the DTBS that you try do not have support for the SD card on your hardware. )
     : FDT /dtb/amlogic/meson-gxbb-vega-s95-pro.dtb
설치, network  성공

 

2. 서버 셋팅

0) 참고 : https://ompanggin.tistory.com/15

1) locale 설정
    - https://jinmay.github.io/2019/11/04/linux/linux-change-locale-to-korean/

2) time zone 설정
    - sudo /usr/bin/timedatectl set-timezone Asia/Seoul

3) fstab 설정
    - https://hanseokhyeon.tistory.com/entry/
우분투에서-하드디스크-자동-마운트하기
    -  HDD idle time 설정, shell-script 작성하여 부팅시 실행

#!/bin/sh -e
HDD_ID='/dev/disk/by-uuid/e1a285c7-7f6b-4b2d-9e6f-056bbd3b9d35'
if [ -e $HDD_ID ]
then
        sudo /sbin/hdparm -B 127 -S 200 $HDD_ID
else
        /bin/echo "HDD is not mounted."
fi

4) 사용자 실행파일 path 설정
    - .profile
$HOME/bin, $HOME/.local/bin 추가되어 있어서 추가 설정 불필요

5) EBS 녹음 설정
    - ffmpeg
설치 : sudo apt-get install ffmpeg
    - baidu
백업용 python module 설치  : sudo pip install bypy
    - EBS
녹음 script 작성 crontab 등록
      [
참고] https://ompanggin.tistory.com/31 

 6) transmission 설치
    -
설치 : sudo apt-get install transmission-daemon transmission-cli
    -
서비스 멈추고 설정 해야함. 종료시 설정파일을 기존 파일로 덮어씀.
       sudo service transmission-daemon stop
       sudo vi /etc/transmission-daemon/settings.json
    -
설정파일 항목 참조 : https://oslinux.tistory.com/9 , https://github.com/transmission/transmission/wiki/Editing-Configuration-Files
     - 실행계정 변경 :
        :
아래 2개의 데몬 파일 내의 User항목을 변경하고, 관련 파일의 소유권을 변경
          (
, USER=debian-transmission -> USER='사용자계정')   
          /etc/systemd/system/multi-user.target.wants/transmission-daemon.service  
          /etc/init.d/transmission-daemon 
         [
참고http://yellowtopaz.tistory.com/195http://m.blog.naver.com/garyang/220395326728

7) samba 설정
    - [
참고] https://devji.tistory.com/entry/Ubuntu-2004--Samba-설치하여-Windows에서-연결하기
    - 설치 : sudo apt-get install samba
    -
사용자 추가 : sudo smbpasswd -a <아이디>
    - samba
설정 아래정도 추가: sudo vi /etc/samba/smb.conf

[common]
   comment = common
   path = /common
   guest ok = no
   browseable = yes
   writable = yes
   create mask = 0664
   directory mask = 0776

 

3. Trouble Shooting

1) samba 속도 느림 1MB/s 정도만 나옴.
   -
공유기와 서버간 cat5  cable 연결, 공유기와 notebook wifi 5G 연결
   -
외부망과 전송시에 정상속도 Max 20MB/s
   -
외장 HDD 아닌 내부 메모리에서 전송해도 느림
   - ftp
느림
   - 2GB
파일을 끝까지 전송 못하고 에러 .@win10
   - network
dhcp 안잡혀서 ip 할당했는데 -> dhcp로해도 마찬가지
   - dtb
바꿔도 안됨.
   - mac address
부팅시 마다 바뀜.
   - ubuntu -> debian
으로 이미지 변경해도 동일.
     Armbian_20.10_Arm-64_focal_current_5.9.0.img    ->      
     Armbian_20.10_Arm-64_buster_current_5.9.0.img
사용

    - 내장메모리에서 읽을 때는 정상속도, USB HDD에서 읽을 때는 느려짐. USB 포트 고장으로 판단됨.
    - Tanix TX3 mini
신규로 구입함. 

Posted by 옴팡진
,

EBS 녹음 (20.12.26)

Electronics 2020. 12. 26. 07:46

-. EBS Internet radio는 HLS (HTTP Live Streaming) 임
   : [참고] https://ompanggin.tistory.com/26

 

EBS 녹음 (18.08.06 외국어채널2 반영)

EBS 녹음 -. 18/08/06 이후로 EBS 외국어 채널 2가 생기면서 녹음해서 듣던 방송의 주소가 변경되고,   스트리밍 방식이 rmtp -> m3u8 로 변경됨. -. m3u8   : HLS (HTTP Live Streaming), 애플이 제안한 방식..

ompanggin.tistory.com

-. 위의 link 에서 Update 함.
    : EBS 주소를 on air 주소로 변경함
    : bydu cloud에 backup 함. (설정 필요)

#!/bin/bash
# v2 : update address. streaming rtmp -> HSL
# internet radio 18:20 Easy, 18:40 Power
# RADIO_ADDR="http://bandibook.ebs.co.kr/bandibook/live_m4a/playlist.m3u8"
# FM 07:20 Easy, 07:40 Power

RADIO_ADDR="http://ebsonairiosaod.ebs.co.kr/fmradiobandiaod/bandiappaac/playlist.m3u8"

PROGRAM_NAME=$1
RECORD_MINS=$(($2 * 60))
DEST_DIR=$3

REC_DATE=`date +%Y%m%d-%H%M`

MP3_FILE_NAME=$PROGRAM_NAME"_"$REC_DATE.mp3

ffmpeg -t $RECORD_MINS -y -i $RADIO_ADDR $MP3_FILE_NAME &>/dev/null

mkdir -p $DEST_DIR

mv $MP3_FILE_NAME $DEST_DIR

#if [ $1 = "EasyEnglish" ] 
#then
#	nohup /usr/local/bin/bypy upload $DEST_DIR/$MP3_FILE_NAME /EBS.Easy.English&
#fi

#if [ $1 = "PowerEnglish" ] 
#then
#	nohup /usr/local/bin/bypy upload $DEST_DIR/$MP3_FILE_NAME /EBS.Power.English&
#fi
Posted by 옴팡진
,

(21.05.22)
다음 사이트의 변경되어서 정상작동하지 않습니다. 
Kodi v19 대응 python 버전으로 변경 중입니다.    

--------
아래의 링크에서 update 함

https://ompanggin.tistory.com/29

 

(update) Kodi: Daum Movie Scraper Add-on 작동법 (2)

우선 아래 링크의 scraper 작성 시 TODO로 남겨 놓았던 항목들을 작성함. https://ompanggin.tistory.com/28 Kodi: Daum Movie Scraper Add-on 작동법 1. 잘 사용하던 Daum Movie Scraper 가 Daum이 서비스를 변경..

ompanggin.tistory.com

[ver 0.4]  [bug fix] 검색결과가 영문 제목이 안나오는 경우 (, 동네사람들) 검색 실패를 수정 (*source 버전을 배포 버전과 맞춤.)

- procedure 

  • ver 0.3  <title>한글제목(영문제목)” 으로 나타내려고한글제목, movieID, 영문제목, year” 한꺼번에 검색
<RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;\2(\3)&lt;/title&gt;&lt;year&gt;\4&lt;/year&gt;&lt;id&gt;\1&lt;/id&gt;&lt;url cache=&quot;daum-movie-\1.json&quot;&gt;http://movie.daum.net/data/movie/movie_info/detail.json?movieId=\1&lt;/url&gt;&lt;/entity&gt;" dest="6">
	<expression clean=“1">movie\.daum\.net[^\?]*\?movieId=(\d*)[^\?]*tit_name&quot;&gt;&lt;b&gt;(.[^"]*)&lt;/b&gt;[^\?]*tit_sub&quot;&gt;(.[^"]*),[^\?]*(\d{4})</expression>
</RegExp>

 

  • 동네사람들" 같이 검색결과에 영문 제목이 없는 경우에 (.[^”]*) 매칭이 안되어 전체 검색 실패함. (* suggest page json 형태로 원래 영문 제목이 없음)
  • ver 0.4 <entity> 항목을 모두 별도로 검색하여 한개가 매칭이 안되더라도 나머지로 검색할 있도록 수정함.
<RegExp conditional="OrigTitleInSrchResult" input="$$6" output="&lt;entity&gt;\1&lt;/entity&gt;" dest="5">
	<RegExp input="$$7" output="&lt;title&gt;\1&lt;/title&gt;" dest="6">
		<RegExp input="$$1" output="\1" dest="7">
			<expression clean="1">movie\.daum\.net.*tit_name&quot;&gt;&lt;b&gt;(.[^"]*)&lt;/b&gt;</expression>
		</RegExp>
		<RegExp input="$$1" output="(\1)" dest="7+">
			<expression clean="1">movie\.daum\.net.*tit_sub&quot;&gt;(.[^"]*),</expression>
		</RegExp>
	<expression noclean="1" />
	</RegExp>
	<RegExp input="$$1" output="&lt;id&gt;\1&lt;/id&gt;&lt;url cache=&quot;daum-movie-\1.json&quot;&gt;http://movie.daum.net/data/movie/movie_info/detail.json?movieId=\1&lt;/url&gt;" dest="6+">
		<expression clean="1">movie\.daum\.net[^\?]*\?movieId=(\d*)</expression>
	</RegExp>
	<RegExp input="$$1" output="&lt;year&gt;\1&lt;/year&gt;" dest="6+">
		<expression clean="1">movie\.daum\.net.*tit_sub&quot;&gt;[^"]*(\d{4})</expression>
	</RegExp>
	<expression noclean="1" />
</RegExp>

 

metadata.movie.daum.net-2.1.4.zip
0.03MB

Posted by 옴팡진
,

우선 아래 링크의 scraper 작성 시 TODO로 남겨 놓았던 항목들을 작성함. https://ompanggin.tistory.com/28

 

Kodi: Daum Movie Scraper Add-on 작동법

1. 잘 사용하던 Daum Movie Scraper 가 Daum이 서비스를 변경하면서 작동이 되지 않음. 2. 다른 부분(detail.json, cast_crew.json, list.json)은 여전히 사용이 가능한데 search api (movie.json)가 작동을 안함...

ompanggin.tistory.com

 

[ ver 0.2 ] CreateSearchUrl : 한글, 숫자 제목만 뽑아서 search keywords로

- 파일명이 “한글 제목.2019.english.title”로 되어 있을때 “한글 제목 2019” 로 검색하도록  함

- Procedure 

  • 파일명 : “한글 제목.2019.english.title.FHDRip.H264.AAC-NonDRM.mp4” 이면 
  • kodi : “한글 제목 2019 english title” 정도로 정리해서 리턴함.
    : https://kodi.wiki/view/Advancedsettings.xml#cleanstrings 여기서 설정 가능함.
  • scrapper : 파일명을 받으면 정규식으로 앞에 나오는 언어의 제목만 뽑아줌.
    : 이때 urlencoding하여 보내주므로 이에 맞게 정규식 적용함. (utf-8인 경우 %e.(?:%\w\w){2} 가 한글)
    : 예, 파일명이 "한글제목.english.title" 라면 kodi는 urlencode 하여 %ed%95%9c%ea%b8%80%ec%a0%9c%eb%aa%a9.english.title) 리턴
    : python 정규식을 따르고 ((?=.*%e.(?:%\w\w){2})(?:%e.(?:%\w\w){2}|\d|[._\-() ]|%20|%5b|%5d)*(?:%e.(?:%\w\w){2})|(?:\w|[._\-() ]|%20|%5b|%5d)*\w) 적용하면
    : “한글제목”만 <CreateSearchUrl> 에 검색어로 추가(english.title.한글제목 의 경우 “english.title”이 선택)
  • 잘 검색이 안될 때는 “한글제목2019” 로 개봉 연도를 붙여서 검색하면 잘됨.

   

[ver 0.3] daum search를 movie 한정, movie 페이지 검색의 suggest 활용

- 다음 movie의 suggest search를 활용하여 영화 한정하여 검색하게 함.
   : 제목을 자세히 썼는데 틀리면 검색안됨. 간단히 써서 리스트에서 선택함.
   : 디렉토리 검색할때는 첫번째 리스트 된 것만 적용하여 오류가 많음.
   : 디렉토리는 search 잘 안찾아지는 페이지는 suggest 로 함.

- Procedure

  • search page 변경 : 기존 http://search.daum.net/search?w=tot&amp;q=\1
    변경 https://suggest-bar.daum.net/suggest?id=movie&amp;cate=movie&amp;multiple=1&amp;mod=json&amp;code=utf_in_out&amp;q=\1
  • 검색어는 ver 0.2에서 앞에 나오는 언어로 선택됨. suggest 검색은 연도가 들어갈 경우 잘 검색이 안되어 연도제외.
  • kodi 리턴하는 json은 …  "movie" : [ “제목|movieID|poster url|개봉연도|검색일치율(?)”, “…" ] 로 되어 있음.
  • 정규식은  json 의 “movie” … 부분을 따다가 제목, movieID, 개봉연도를 parsing 함.
    <RegExp input="$$6" output="<entity><title>\1</title><year>\4</year><id>\2</id><url cache="daum-movie-\2.json">http://movie.daum.net/data/movie/movie_info/detail.json?movieId=\2</url></entity>" dest="5">
        <RegExp input="$$1" output="\1" dest=“6">
              <expression>.*"movie".*?:.*?\[(.*?)\]</expression>
        </RegExp>
        <expression repeat="yes" clean="1">"(.*?)\|(\d+)\|(.*?)\|(\d+)\|.*?"</expression>
    </RegExp>

 

[ ver 0.4 ] suggest page search 를 옵션화 + zip 파일 생성

- Procedure

  • addon.xml : bug fix <description lang=“kr”> -> <description lang=“ko”>
    current version에 대한 간단한 설명
  • resource/settings.xml : Search Suggest 추가
    <setting label="30008" type="bool" id="SearchSuggest" default="false"/>
  • resource/language/Korean/strings.xml : 항목 이름 추가
    <string id="30008">Daum Suggest 사용</string>
  • <RegExp 에 conditional 추가. 이외의 영역에 추가하면 작동안함.
    <RegExp conditional=“!SearchSuggest" …. search page 검색 …
    <RegExp conditional=“SearchSuggest"  …. suggest page 검색 …

- zip 파일로 설치시 addon 설치 에러나면 재부팅하면 정상 설치됨 . (OSX에서 압축한 것도 정상설치)

 

[TODO] Daum TV Scrapper

- 기존 소스의 살아있는 link 가 없고 처리해야할 항목도 많아서 시간이 좀 걸리지만... 

(혼란을 막기 위해 최신 version 만 남기고  지난 version은 삭제함.)

Posted by 옴팡진
,

1. 잘 사용하던 Daum Movie Scraper 가 Daum이 서비스를 변경하면서 작동이 되지 않음. 

2. 다른 부분(detail.json, cast_crew.json, list.json)은 여전히 사용이 가능한데 search api (movie.json)가 작동을 안함. 

3. Kodi Scraper How-To : https://kodi.wiki/view/Scrapers 를 참고함.

4. 기존 개발된  scraper를 기반으로 Daum 검색페이지를 parsing 해서 작동은 가능하도록 수정함

    - https://github.com/hojel/metadata.movie.daum.net 을 설치함. (* Plex daum agent 만드신 분이네요)

    - <CreateSearchUrl >  http:://~~, <GetSearchResults> <expression> 부분을 수정함.

    - 수정 전

<CreateSearchUrl dest="3">
        <RegExp input="$$1" output="&lt;url&gt;http://movie.daum.net/data/movie/search/v2/movie.json?size=20&amp;start=1&amp;searchText=\1&lt;/url&gt;" dest="3">
            <expression noclean="1" />
        </RegExp>
    </CreateSearchUrl>
<GetSearchResults dest="4">
        <RegExp input="$$5" output="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;&lt;results&gt;\1&lt;/results&gt;" dest="4">
            <RegExp conditional="!OrigTitleInSrchResult" input="$$1" output="&lt;entity&gt;&lt;title&gt;\2&lt;/title&gt;&lt;year&gt;\4&lt;/year&gt;&lt;id&gt;\1&lt;/id&gt;&lt;url cache=&quot;daum-movie-\1.json&quot;&gt;http://movie.daum.net/data/movie/movie_info/detail.json?movieId=\1&lt;/url&gt;&lt;/entity&gt;" dest="5">
                <expression repeat="yes" trim="2,3">"movieId":(\d+),"titleKo":"([^"]*)","titleEn":"?([^",]*)"?,[^}]*"prodYear":(\d*)</expression>
            </RegExp>
            <RegExp conditional="OrigTitleInSrchResult" input="$$6" output="\1" dest="5">
                <RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;\2(\3)&lt;/title&gt;&lt;year&gt;\4&lt;/year&gt;&lt;id&gt;\1&lt;/id&gt;&lt;url cache=&quot;daum-movie-\1.json&quot;&gt;http://movie.daum.net/data/movie/movie_info/detail.json?movieId=\1&lt;/url&gt;&lt;/entity&gt;" dest="6">
                    <expression repeat="yes" trim="2,3">"movieId":(\d+),"titleKo":"([^"]*)","titleEn":"?([^",]*)"?,[^}]*"prodYear":(\d*)</expression>
                </RegExp>
                <expression noclean="1" />
            </RegExp>
            <expression noclean="1" />
        </RegExp>
    </GetSearchResults>

    - 수정 후 

<CreateSearchUrl dest="3">
        <RegExp input="$$1" output="&lt;url&gt;http://search.daum.net/search?w=tot&amp;q=\1&lt;/url&gt;" dest="3">
            <expression noclean="1" />
        </RegExp>
    </CreateSearchUrl>
    <GetSearchResults dest="4">
        <RegExp input="$$5" output="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;&lt;results&gt;\1&lt;/results&gt;" dest="4">
            <RegExp conditional="!OrigTitleInSrchResult" input="$$1" output="&lt;entity&gt;&lt;title&gt;\2&lt;/title&gt;&lt;year&gt;\4&lt;/year&gt;&lt;id&gt;\1&lt;/id&gt;&lt;url cache=&quot;daum-movie-\1.json&quot;&gt;http://movie.daum.net/data/movie/movie_info/detail.json?movieId=\1&lt;/url&gt;&lt;/entity&gt;" dest="5">
                <expression clean="1">movie\.daum\.net[^\?]*\?movieId=(\d*)[^\?]*tit_name&quot;&gt;&lt;b&gt;(.[^"]*)&lt;/b&gt;[^\?]*tit_sub&quot;&gt;(.[^"]*),[^\?]*(\d{4})</expression>
            </RegExp>
            <RegExp conditional="OrigTitleInSrchResult" input="$$6" output="\1" dest="5">
                <RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;\2(\3)&lt;/title&gt;&lt;year&gt;\4&lt;/year&gt;&lt;id&gt;\1&lt;/id&gt;&lt;url cache=&quot;daum-movie-\1.json&quot;&gt;http://movie.daum.net/data/movie/movie_info/detail.json?movieId=\1&lt;/url&gt;&lt;/entity&gt;" dest="6">
                    <expression clean="1">movie\.daum\.net[^\?]*\?movieId=(\d*)[^\?]*tit_name&quot;&gt;&lt;b&gt;(.[^"]*)&lt;/b&gt;[^\?]*tit_sub&quot;&gt;(.[^"]*),[^\?]*(\d{4})</expression>
                </RegExp>
                <expression noclean="1" />
            </RegExp>
            <expression noclean="1" />
        </RegExp>
    </GetSearchResults>

 

5. TODO

    - daum search를 movie 한정, movie 페이지 검색의 suggest 활용 (plex daum agent 에서 활용 중)

    - CreateSearchUrl : 한글, 숫자 제목만 뽑아서 search keywords로

    - GetSearchResults : 정규식 고도화 (아무것도 모르고 카피함. ^^;;)

    - 검색안되는 것들 메뉴얼 검색해서 movieId만 넣어도 되도

    - zip 으로 배포되도록

(혼란을 막기 위해 최신 version 만 남기고  지난 version은 삭제함.)

Posted by 옴팡진
,