스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
앱에 라이브 텍스트 상호 작용 추가
정지 사진 또는 일시 정지된 비디오 프레임에 대한 라이브 텍스트 지원을 앱에 구현하는 방법을 알아보세요. iOS, iPadOS 또는 macOS의 모든 이미지 보기 내에서 텍스트 상호 작용, 번역, 데이터 감지 및 QR 코드 스캐닝을 손쉽게 활성화하는 방법을 소개합니다. 또한 상호 작용 유형 제어, 보조 인터페이스 관리, 잠재적 동작 충돌 해결 방법에 대해 다룹니다. 라이브 카메라 피드의 감지된 데이터 캡처 및 상호 작용에 대해 자세히 알아보려면 WWDC22의 ‘Capture machine-readable codes and text with VisionKit(VisionKit을 통한 컴퓨터 판독 코드 및 텍스트 캡처)'를 시청하시기 바랍니다.
리소스
관련 비디오
WWDC23
WWDC22
-
다운로드
♪ 잔잔한 힙합 연주 음악 ♪ ♪ 안녕하세요 저는 Adam Bradford입니다 VisionKit 팀의 엔지니어죠 여러분의 앱에 Live Text를 추가하고 싶다면 제대로 찾아오셨습니다 그런 우선 Live Text가 뭘까요? Live Text는 이미지를 분석하고 사용자들이 그 콘텐츠와 상호 작용하는 기능을 제공합니다 텍스트를 선택해서 복사하고 색인 및 번역과 같은 동작을 수행하고 데이터 감지 작업 흐름을 제공합니다 가령 주소 매핑이나 전화 걸기나 URL로 이동하기가 있습니다 Live Text는 QR code 상호 작용도 허용합니다 이걸 여러분의 앱에서 사용할 수 있다면 어떨까요? 자세히 알고 싶으시다고요? 제대로 찾아오셨습니다 이번 세션에서는 Live Text API에 대한 일반 개요로 시작해보겠습니다 그리고 이 API를 기존 애플리케이션에서 실행하는 방법을 알아보겠습니다 다음으로 몇 가지 조언과 비결을 알려드릴 텐데요 그건 여러분이 Live Text를 앱에 추가할 때 도움이 될 수 있죠 이제 Live Text API의 개요로 들어갑니다 높은 수준에서 Live Text API는 Swift에서 이용 가능합니다 정지 이미지에 멋지게 작동하고 조절해서 일시 정지된 영상 프레임에 쓰일 수 있습니다 실시간 카메라 스트림에서 영상을 분석해서 텍스트나 QR 코드 같은 항목들을 검색해야 한다면 VisionKit에는 이용 가능한 데이터 스캐너도 있습니다 더 자세한 내용은 제 동료 Ron의 이 세션에서 확인해보세요 iOS 16부터 Live Text API를 이용할 수 있습니다 Apple Neural Engine이 있는 기기들과 macOS 13을 지원하는 모든 기기들에서요 그건 네 가지 주요 클래스로 구성됩니다 사용을 위해선 먼저 이미지가 필요합니다 이 이미지는 ImageAnalyzer로 입력되는데 거기에선 비동기 분석을 수행합니다 일단 분석이 완료되면 그 결과물인 ImageAnalysis 객체가 ImageAnalysisInteraction이나 ImageAnalysisOverlayView로 제공됩니다, 플랫폼에 따라서요 지금까진 아주 간단하죠? 이제 기존 애플리케이션에 그걸 추가하는 방법을 제가 시연해보겠습니다 이게 우리 애플리케이션입니다 단순한 이미지 뷰어로 여기엔 스크롤 뷰 내에 이미지 뷰가 있습니다 제가 줌과 팬을 모두 할 수 있다는 점에 주목하세요 그런데 아무리 노력해도 이 텍스트는 전혀 선택할 수 없고 이 데이터 감지자들도 전혀 활성화할 수 없습니다 이걸론 그냥 불가능하죠 이건 Xcode로 된 그 프로젝트입니다 이 애플리케이션에 Live Text를 추가하기 위해 저는 뷰 컨트롤러 서브클래스를 수정하겠습니다 먼저 ImageAnalyzer와 ImageAnalysisInteraction이 필요합니다 여기에서 저는 viewDidLoad를 중단시키고 이미지뷰에 상호 작용을 추가하고 있습니다 다음으로 저는 분석을 언제 수행해야 할지 알아야 합니다
주목할 점은 새로운 이미지가 정해지면 저는 preferredInteractionTypes와 분석을 재설정합니다, 그것들은 예전 이미지를 위한 거였죠 이제 새로운 분석을 위한 모든 게 준비됐습니다 다음으로 저는 우리가 사용할 함수를 만들고 우리 이미지가 존재하는지 확인하겠습니다
존재한다면 작업을 만듭니다 다음으론 설정을 만들어서 분석자에 뭘 찾아야 하는지 알려줍니다 이 경우에는 저는 텍스트 및 기계가 읽을 수 있는 코드를 쓰죠 분석을 생성하면 throw할 수 있으니 그걸 적절한 것으로 처리해주세요 이제 마지막으로 analyzeImageWithConfiguration 기법을 호출할 준비가 됐는데 그건 분석 과정을 시작해줍니다 일단 분석이 완료되면 쉽게 가늠할 수 없는 시간이 경과했고 애플리케이션의 상태가 바뀌었을 수 있으니 저는 분석이 성공했는지와 디스플레이 이미지가 바뀌지 않았는지 확인하겠습니다 확인 결과가 모두 통과면 상호 작용에 분석을 정한 다음 preferredInteractionTypes를 정하기만 하면 됩니다 여기에서 전 .automatic을 쓰는데 그건 제게 기본 설정 시스템 행동을 줍니다 이거 테스트할 준비가 된 것 같네요 저것 좀 보세요 Live Text 버튼이 뜬 게 보입니다 그리고… 네, 이제 텍스트를 선택할 수 있어요 이 인터페이스 요소들이 자동으로 위치를 잡아주는 데 주목하세요 그것들의 위치를 이미지 경계와 가시 영역 모두의 내부에 유지하는 것도요 제 노력은 필요 없고요 좋아요, 주목할 점은 Live Text 버튼을 두드리면 선택 가능한 모든 항목을 강조하고 데이터 감지기에 밑줄을 쳐주고 Quick Actions를 보여주는 겁니다 저는 이 Quick Action을 편하게 두드려서 전화하고 길게 눌러서 추가 옵션도 볼 수 있습니다 이건 꽤 멋지다는 걸 인정할 수밖에 없죠 이 코드 몇 줄만으로 저는 평범한 이미지를 갖고 거기에 활기를 불어 넣었습니다 이 간단한 애플리케이션에는 이제 이미지에서 텍스트를 선택하고 데이터 감지기를 활성화하고 QR 코드, 색인, 텍스트 번역 등의 기능이 있습니다 코드 몇 줄 치고 그리 초라하진 않습니다 저한테 물어보신다면요 이제 여러분이 Live Text를 실행하는 방법을 알게 됐으니 여러분의 채택에 도움이 될 수 있는 몇 가지 조언과 비결을 알아보겠습니다 상호 작용 타입을 탐색하면서 시작해보겠습니다 대부분의 개발자는 .automatic을 원할 겁니다 그건 텍스트 선택을 제공하지만 Live Text 버튼이 작동하면 데이터 감지기를 강조하기도 합니다 이는 모든 적용 가능한 감지된 항목들 아래에 줄을 긋고 1회 탭 접근을 허용해서 그것들을 활성화합니다 이는 내장 애플리케이션에서 여러분이 볼 행동과 정확히 똑같습니다 여러분의 앱에 데이터 감지기가 없으면서 텍스트 선택만 있는 게 합리적이라면 여러분은 타입을 textSelection으로 정해도 되고 그건 Live Text 버튼의 상태로 변하지 않을 겁니다 그런데 여러분의 앱이 텍스트 선택 없이 데이터 감지기만 갖추는 게 합리적이라면 타입을 .dataDetectors로 정하세요 주목할 점은 이 모드에선 선택이 불가능하므로 Live Text 버튼은 보이지 않겠지만 데이터 감지기에는 밑줄이 있고 1회 탭 접근을 위한 준비가 될 것입니다 preferredInteractionTypes를 빈 세트로 정하는 건 상호 작용을 불가능하게 합니다 또한 마지막 주의 사항은 텍스트 선택이나 자동 모드에서 길게 눌러서 데이터 탐지기를 활성화활 수 있다는 걸 알아낼 겁니다 이것을 제어하는 건 allowLongPressForDataDetectorsIn TextMode 속성인데 그걸 참으로 설정하면 작동하는데 그게 기본 설정입니다 필요하다면 이를 거짓으로 정해서 작동하지 않게 하세요 이제 잠시 시간을 들여 하단에 있는 버튼들을 설명하고 싶은데 이들은 합쳐서 보완 인터페이스로 알려져 있습니다 이는 Live Text 버튼으로 구성됩니다 그 버튼은 보통 우측 하단 구석에 있죠 Quick Actions로도 구성됩니다 그건 좌측 하단에 나옵니다 Quick Actions는 분석에서 나온 모든 데이터 감지기를 나타내고 Live Text button이 작동하면 보입니다 그 크기와 위치와 가시성은 상호 작용에 의해 제어됩니다 기본 설정 위치와 외형은 시스템과 일치할지라도 여러분의 앱엔 맞춤형 인터페이스 구성 요소가 있을 수 있는데 그건 방해하거나 다양한 폰트나 기호 무게값을 활용할 수 있습니다 여러분이 이 인터페이스를 맞춤화할 방법을 살펴보죠 우선 isSupplementary InterfaceHidden 속성입니다 제 앱이 텍스트를 선택하는 걸 허용하길 원하지만 Live Text 버튼을 보여주는 건 원치 않을 때 제가 Supplementary InterfaceHidden을 참으로 정하면 Live Text 버튼이나 Quick Actions는 안 보일 겁니다 콘텐츠 인셋 속성도 이용 가능합니다 여러분의 인터페이스 요소들이 보완 인터페이스와 겹친다면 여러분은 콘텐츠 인셋을 조절해서 Live Text 버튼과 Quick Actions가 보일 때 여러분의 기존 앱 콘텐츠에 잘 조정되게 합니다 그 인터페이스가 채택하길 원하는 맞춤형 폰트를 여러분의 앱이 사용 중이라면 supplementaryInterfaceFont를 설정하면 Live Text 버튼과 Quick Actions가 텍스트의 경우 명시된 폰트를 기호의 경우 폰트 무게를 사용하게 할 겁니다 주의할 점은 버튼 크기 지정 일관성을 위해 Live Text는 포인트 크기를 무시한다는 겁니다 잠시 주제를 바꾸죠 여러분이 UIImageview를 사용하지 않는다면 하이라이트가 이미지와 일치하지 않는다는 걸 발견할 수 있습니다 그 이유는 UIImageView의 경우 VisionKit가 그 ContentMode 속성을 써서 여러분을 위해 contentsRect를 자동으로 계산할 수 있기 때문이죠 여기에서 상호 작용의 뷰는 그 이미지 콘텐츠보다 경계가 크지만, 기본 설정의 콘텐츠 렉트를 사용하는데 그건 단위 직사각형입니다 이건 쉽게 풀립니다, 대표 기법인 contentsRectForInteraction을 실행하고 단위 좌표 공간에 직사각형을 돌려주는 방식으로요 이걸 바로잡기 위해 이미지 콘텐츠가 상호 작용의 경계와 관련되는 방식을 설명하는 거죠 예를 들어 이 값들이 있는 직사각형을 돌려주는 건 문제를 바로잡아주겠지만 여러분 앱의 현재 콘텐츠와 레이아웃을 바탕으로 정규화된 올바른 직사각형을 돌려주십시오 상호 작용의 경계가 바뀔 때마다 contentsRectForInteraction이 호출됩니다, 그런데 여러분의 contentsRect가 바뀌었으나 여러분 상호 작용의 경계는 바뀌지 않았으면 상호 작용에 업데이트를 요구할 수 있습니다 setContentsRectNeedsUpdate()를 호출하는 방식으로요 Live Text를 채택할 때 여러분이 떠올릴 수 있는 또 하나의 질문은 이 상호 작용을 놓을 가장 좋은 곳이 어디냐는 겁니다 이상적으로 Live Text 상호 작용은 여러분의 이미지 콘텐츠를 주관하는 뷰에 직접 놓습니다 앞에서 언급했듯 UIImageView는 여러분을 위해 contentsRect 계산을 처리해줍니다 그건 필수는 아니지만 선호되긴 합니다 여러분이 UIImageview를 사용한다면 imageView의 상호 작용을 정하면 VisionKit가 나머지를 처리해줄 겁니다 하지만 여러분의 ImageView가 ScrollView 내에 위치해 있다면 상호 작용을 ScrollView에 놓고 싶은 마음이 생길 수 있죠 하지만 그건 추천하지 않습니다 관리하기 힘들 수 있어요 거기엔 계속해서 변하는 contentsRect가 있을 테니까요 그때 해결책도 동일합니다 여러분의 이미지 콘텐츠를 주관하는 뷰에 상호 작용을 놓습니다 확대가 적용된 상태로 그게 ScrollView 내에 있더라도요 잠시 제스처 얘기를 하겠습니다 아무리 작게 봐도 Live Text에는 제스처 인식자들이 아주 넉넉하게 있습니다 여러분의 앱이 구성된 방식에 따라 여러분은 발견할 수 있습니다 상호 작용이 실은 여러분의 앱이 처리해야 할 제스처나 이벤트에 반응하는 걸요 혹은 그 반대도요 당황하지 마세요 그런 문제들이 발생하는 걸 보면 바로잡는 걸 돕게 사용할 수 있는 몇 가지 기술은 다음과 같습니다 이를 바로잡는 하나의 흔한 방법은 다음의 대표 기법을 실행하는 겁니다 interactionShouldBeginAtPointFor InteractionType입니다 여러분이 거짓을 돌려주면 그 동작은 수행되지 않습니다 시작점으로 좋은 곳은 그 상호 작용이 주어진 포인트에 상호 작용 항목이 있는지 확인하는 겁니다 아니면 작동하는 텍스트 선택이 있는지를요 여기에서 텍스트 선택 확인을 사용하는 건 여러분이 텍스트를 벗어난 곳을 두드려서 그것의 선택을 해제할 수 있게 하는 겁니다 반면에 여러분이 자신의 상호 작용이 제스처에 반응하지 않는 것 같다고 느끼면 이유는 여러분의 앱에 제스처 인식자가 그 일들을 처리하고 있기 때문일 수 있습니다 이 경우에 여러분은 유사한 해결책을 만들 수 있습니다 gestureRecognizer의 gestureRecognizerShouldBegin 대표 기법을 사용해서요 여기에서 전 유사한 확인을 하고 거짓을 돌려줍니다 그 위치에 대화형 항목이 있거나 작동되는 텍스트 선택이 있다면요 여담인데 이 사례에서 저는 먼저 gestureRecognizer의 위치를 창 좌표 공간으로 전환시킵니다 nil을 전달해 넣은 다음 그걸 상호 작용의 뷰로 전환하는 방식으로요 여러분의 상호 작용이 확대가 적용된 상태로 ScrollView 내에 있으면 그것이 필요할 수 있습니다 여러분의 포인트들이 일치하지 않는 걸 발견하면 이 기술을 시도해보세요 제가 유용하게 느낀 또 하나의 유사한 옵션은 UIView의 hitTest:WithEvent를 중단시키는 겁니다 여기에서도 다시 비슷한 얘깁니다 저는 이전과 동일한 종류의 확인을 수행하고 이 경우에는 적절한 뷰를 돌려줍니다 늘 그렇듯 우린 여러분의 앱이 가능한 한 반응성이 좋길 바라고 Neural Engine이 분석을 지극히 효율적으로 만들긴 해도 최고의 성과를 위한 ImageAnalyzer 조언을 몇 가지 알려드리고 싶습니다 이상적으로는 여러분의 앱에서 ImageAnalyzer를 하나만 공유하는 게 좋습니다 우린 몇 가지 종류의 이미지를 지원합니다 여러분은 이미지 전환을 늘 최소화해야 합니다 여러분이 갖고 있는 네이티브 타입을 전달해 넣어서요 하지만 여러분한테 우연히도 CVPixelBuffer가 있다면 그게 가장 효율적일 겁니다 또한 시스템 자원을 최고로 활용하기 위해 여러분은 이미지가 화면이 나타나는 순간이나 그 직전에 분석을 시작해야 합니다 여러분 앱의 콘텐츠가 스크롤하면… 예를 들어 거기에 일정표가 있다면 스크롤링이 멈췄을 때만 분석을 시작하세요 여러분이 Live Text를 볼 곳은 이 API만이 아닙니다 여러분의 앱이 이미 사용하고 있는 시스템에 걸친 프레임워크들에서 지원이 자동으로 제공됩니다 예를 들어 UITextField나 UITextView에는 키보드 입력용 Camera를 쓰는 Live Text 지원이 있습니다 Live Text는 WebKit와 Quick Look에서도 지원됩니다 자세한 정보를 얻으려면 이 세션들을 확인해보세요 올해 iOS 16에서 새로운 건 Live Text가 지원되는 AVKit를 추가했다는 겁니다 AVPlayerView와 ViewController는 Live Text를 일시 정지된 프레임에서 자동으로 지원합니다 allowsVideoFrameAnalysis 속성을 통해서요 그건 기본 설정에서 활성화되어 있습니다 주의할 점은 이게 non-FairPlay 보호 콘텐츠에서만 이용할 수 있다는 겁니다 여러분이 AVPlayerLayer를 사용한다면 여러분은 그 분석과 상호 작용을 관리하는 데 책임이 있지만 현재 프레임을 얻기 위해 currentlyDisplayedPixelBuffer 속성을 사용하는 게 아주 중요합니다 이는 적절한 프레임이 분석되는 중이란 걸 보장하는 유일한 방법입니다 그건 영상 재생률이 0일 때만 유효한 값을 돌려줍니다 그리고 이건 섈로 사본이고 거기에 작성하는 건 결코 안전하지 않습니다 그리고 이번에도 non-FairPlay 보호 콘텐츠에서만 이용할 수 있습니다 Live Text 기능을 여러분의 앱에 가져올 수 있어서 기분이 짜릿하네요 Live Text 팀원들 모두를 대신해서 인사드려요 이번 세션에 함께해주셔서 감사합니다 여러분의 앱에서 그걸 이미지에 사용하는 걸 보길 많이 기대합니다 그리고 늘 그렇듯, 즐기세요 ♪
-
-
2:37 - Live Text Sample Adoption
import UIKit import VisionKit class LiveTextDemoController: BaseController, ImageAnalysisInteractionDelegate, UIGestureRecognizerDelegate { let analyzer = ImageAnalyzer() let interaction = ImageAnalysisInteraction() override func viewDidLoad() { super.viewDidLoad() imageview.addInteraction(interaction) } override var image: UIImage? { didSet { interaction.preferredInteractionTypes = [] interaction.analysis = nil analyzeCurrentImage() } } func analyzeCurrentImage() { if let image = image { Task { let configuration = ImageAnalyzer.Configuration([.text, .machineReadableCode]) do { let analysis = try await analyzer.analyze(image, configuration: configuration) if let analysis = analysis, image == self.image { interaction.analysis = analysis; interaction.preferredInteractionTypes = .automatic } } catch { // Handle error… } } } } }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.