지난 주 YesWeScan라이브러리에서만 인식률이 좋았던 이유에 대해서 분석해본 결과 전달받은 AVCapturePhoto를 UIImage로 타입캐스팅한 결과 인식률이 좋지 않았고 CMSampleBufffer를 CIImage로 타입캐스팅하여 사용해야 인식률이 좋았다.
추가로 직접 캡처동작을 트리거하지 않고 매 프레임을 입력받아 자동으로 텍스트가 인식되면 처리하기 위해 고민해본 결과 AVCapturePhoto를 사용하지 않고 AVCaptureVideo를 사용하면 매 프레임을 입력받고 입력받은 CMSampleBuffer를 CIImage로 타입캐스팅 후 Vision을 통해 텍스트를 인식하게 되면 자동으로 텍스트가 인식된 경우를 처리할 수 있었다.
지난 주 Youtube 특정채널 동영상목록을 가져오는 파이썬 스크립트를 작성했다.
특정채널 동영상목록이 매우 많은 경우 무료 API 제한량이 있어서 딜레이를 지정해도 모든 동영상을 가져오지 못하는 경우도 있고, 재생목록내의 동영상이 따로 있는 경우도 있어서 재생목록 내의 동영상목록을 가져오는 파이썬 스크립트를 추가작성했다.
🔗 Youtube API Docs - playlistitem
import requests
import time
# Step 1: API 설정
API_KEY = '' # 실제 API 키 작성
PLAYLIST_ID = '' # 재생목록 ID
CHANNEL_ID = '' # 제목을 가져올 채널 ID
MAX_RESULTS = 50 # 한 번에 가져올 결과 수 (최대 50)
# 유튜브 데이터 API v3 playlistItems 엔드포인트 기본 URL
youtube_url = 'https://www.googleapis.com/youtube/v3/playlistItems'
# API 요청에 필요한 매개변수
params = {
'part': 'snippet',
'maxResults': MAX_RESULTS,
'playlistId': PLAYLIST_ID,
'key': API_KEY
}
# 재생목록에서 비디오 제목과 URL을 가져오는 함수
def fetch_playlist_video_titles_and_urls():
videosResult = []
next_page_token = None
index = 1 # 동영상 인덱스 시작값
while True:
if next_page_token:
params['pageToken'] = next_page_token
# Step 2: 유튜브 데이터 API에 GET 요청 보내기
response = requests.get(youtube_url, params=params)
data = response.json()
# Step 3: 비디오 제목 및 URL 추출
for item in data['items']:
title = item['snippet']['title']
video_id = item['snippet']['resourceId']['videoId']
video_url = f'https://www.youtube.com/watch?v={video_id}&list={PLAYLIST_ID}&index={index}'
videosResult.append((title, video_url))
index += 1
# 다음 페이지가 있는지 확인
next_page_token = data.get('nextPageToken')
# 다음 페이지가 있을 경우, 61초 대기
if not next_page_token:
break
return videosResult
# 제목과 URL을 텍스트 파일에 저장하는 함수
def save_titles_and_urls_to_file(videos, filename='playlist_video_titles_and_urls.txt'):
with open(filename, 'w', encoding='utf-8') as file:
for index, (title, url) in enumerate(videos, start=1):
file.write(f"{index}. **[{title}]({url})**\n\n")
# 코드 실행
videos = fetch_playlist_video_titles_and_urls()
save_titles_and_urls_to_file(videos)
iOS에서는 몇몇 시스템을 사용하기 위해서는 접근권한등이 필요합니다. 예를 들어, 위치권한이 필요한 경우 위치정보에 접근할 수 있는 권한이 필요합니다.
접근권한의 상태등을 알 수 있는 방법은 AuthorizationStatus라는 enum객체를 사용할 수 있습니다.
위치접근권한은 CLAuthorizationStatus로 case가 약간 다르지만 대부분의 case들의 종류는 3가지 (Authorized
, Denied
, NotDetermined
)를 자주 사용합니다.
Authorized
: 권한이 허용된 상태Denied
: 권한이 거부된 상태NotDetermined
: 권한허용여부를 물어보지 않은 상태그럼 notDetermined는 권한허용여부를 물어보지 않은 상태인데 앱이 처음 시작할 때 무조건 권한허용여부를 물어본 상태에도 가끔씩 notDetermined로 설정된 경우가 있을 수 있는 부분이 있어서 의아해서 검색해보았지만 오류가 발생할 수 있다는 내용만 찾았다.
권한요청을 하는 클로저내에서 UI관련 작업들은 메인스레드를 주의해서 사용할 필요가 있다.
[A-Z0-91{2}_[A-Z0-9]{2}_[A-Z0-9]{2}
와 ([A-Z0-9]{2}_){2}[A-Z0-9]{2}
는 동일하다.@objc func keyboardWillShow(note: NSNotification) {
if let keyboardSize = (note.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
var keyboardHeight = CGFloat(Int(keyboardSize.height))
self.scrollView.snp.updateConstraints {
$0.bottom.equalToSuperView().offset(-keyboardHeight)
}
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
}