함수의 미디어 읽기와 업로드
함수는 미디어 집합(Media set)의 파일이나 객체의 미디어 참조 속성을 입력으로 받아 읽고 변환할 수 있습니다. TSv2와 Python은 Media, TSv1은 MediaItem을 사용합니다. 첨부 파일과는 저장 및 처리 API가 다릅니다.
언어별 범위
| 기능 | TSv1 | TSv2와 Python |
|---|---|---|
| 기존 미디어 읽기와 객체 속성에 연결 | 지원 | 지원 |
| 함수에서 새 미디어 업로드 | 지원하지 않음 | 지원 |
| 기본 처리 방식 | 타입별 내장 MediaItem 메서드 | OSDK Media와 변환 작업 |
| 메모리 고려 | 20 MB 미만 파일 권장 | 함수의 설정된 메모리와 실행 시간 적용 |
라이브 미리보기에서 미디어 입력을 받을 때는 미디어 집합을 검색하고 항목을 직접 선택할 수 있습니다. 미디어 참조 문자열을 수동으로 입력할 필요가 없습니다.
Media와 MediaReference
TSv2의 Media는 @osdk/client에서, Python은 functions.api 또는 foundry_sdk_runtime.media에서 가져옵니다. 객체의 미디어 속성, 함수의 입력, 임시 업로드 반환에 같은 타입을 사용하고 함수의 출력으로도 반환할 수 있습니다.
MediaReference는 파일 위치를 식별하는 값이며 Media는 그 참조에 내용 조회와 메타데이터 메서드를 제공하는 객체입니다. getMediaReference() 또는 get_media_reference()로 내부 참조를 읽습니다.
아래 표의 버전 조건은 서로 다른 패키지와 생성기의 버전입니다.
| 기능 | 버전 조건 |
|---|---|
| TSv2 미디어 편집 | TypeScript OSDK 2.16 이상 |
| uploadMedia가 Media를 반환 | TypeScript OSDK 생성기 2.20 이상. 이전에는 MediaReference 반환 |
| TSv2 전체 메타데이터 | @osdk/client 2.56.0 이상 |
| transformAndWait 이름과 media 인수 | @osdk/api 2.55.0 이상 |
| Python 객체 미디어 편집 | Python OSDK 2.198 이상 |
아래 TSv2 업로드 및 변환 예제는 Media를 반환하는 생성기를 사용합니다.
내용과 메타데이터
| 목적 | TSv2 | Python |
|---|---|---|
| 원본 바이트 | fetchContents()의 Response에서 blob() 또는 arrayBuffer() | get_media_content()의 BytesIO |
| 기본 메타데이터 | fetchMetadata(): path, sizeBytes, mediaType | get_media_metadata(): path, size_bytes, media_type |
| 타입별 전체 메타데이터 | fetchFullMetadata()의 itemMetadata | get_media_full_metadata()의 item_metadata |
| 내부 참조 | getMediaReference() | get_media_reference() |
TSv2 fetchContents의 Response는 ok와 상태를 확인한 뒤 내용을 읽습니다. 다음 함수는 UTF-8 텍스트 미디어를 읽습니다. 이미지, 오디오나 문서 바이너리는 해당 형식의 파서로 처리해야 합니다.
import type { Media } from "@osdk/client";
export default async function readTextMedia(media: Media): Promise<string> {
const response = await media.fetchContents();
if (!response.ok) throw new Error(`미디어 읽기 실패: ${response.status}`);
return response.text();
}
Python은 바이너리 반환을 지원하므로 원본 바이트를 반환할 수 있습니다.
from functions.api import Media, function
@function
def read_media_bytes(media: Media) -> bytes:
return media.get_media_content().getvalue()
전체 메타데이터의 타입 구분
문서에는 pages와 title, 이미지에는 dimensions와 bands처럼 타입별 필드가 있습니다. 먼저 itemMetadata.type 또는 Python variant 클래스로 좁혀야 합니다.
TSv2는 document, imagery, audio, video, spreadsheet, model3d, dicom, email, untyped를 모델링합니다. 설치 SDK가 모르는 새 플랫폼 타입은 unknown으로 표현하고 raw에 원래 내용을 보존합니다. unknown과 모든 파일 형식을 받는 미디어 집합의 실제 플랫폼 타입 untyped는 다릅니다.
fetchFullMetadata는 외부 Media 구현의 소스 호환성을 위해 인터페이스에서 선택 메서드이지만 OSDK가 반환하는 Media는 이를 구현합니다. 문서 페이지 수를 읽는 예제는 다음과 같습니다.
import type { Media } from "@osdk/client";
import { Integer } from "@osdk/functions";
export default async function documentPageCount(media: Media): Promise<Integer> {
const item = (await media.fetchFullMetadata?.())?.itemMetadata;
if (item?.type !== "document" || item.pages === undefined) {
throw new Error("페이지 수가 있는 문서 미디어가 필요합니다.");
}
return item.pages;
}
Python은 DocumentMediaItemMetadata나 ImageryMediaItemMetadata와 isinstance를 사용합니다.
from foundry_sdk.v2.media_sets.models import DocumentMediaItemMetadata
from functions.api import Integer, Media, function
@function
def document_page_count(media: Media) -> Integer:
item = media.get_media_full_metadata().item_metadata
if not isinstance(item, DocumentMediaItemMetadata) or item.pages is None:
raise ValueError("페이지 수가 있는 문서 미디어가 필요합니다.")
return item.pages
이미지 전체 메타데이터에서는 dimensions가 없을 수 있으므로 폭과 높이를 사용하기 전에 존재 여부를 확인해야 합니다.
새 텍스트 미디어 업로드
TSv2는 uploadMedia에 Blob과 fileName을 전달합니다. uploadMediaItem.ts에 작성합니다.
import type { Client, Media } from "@osdk/client";
import { uploadMedia } from "@osdk/functions";
export default async function uploadMediaItem(client: Client, body: string, fileName: string): Promise<Media> {
return uploadMedia(client, { data: new Blob([body], { type: "text/plain" }), fileName });
}
Python의 동기 및 비동기 업로드는 같은 입력을 사용합니다.
from functions.api import Media, function
from ontology_sdk import FoundryClient
@function
def upload_media(body: str, media_set_filename: str) -> Media:
return FoundryClient().ontology.media.upload_media(
body=body.encode("utf8"), filename=media_set_filename,
)
@function
async def upload_media_async(body: str, media_set_filename: str) -> Media:
return await FoundryClient().ontology.media.async_upload_media(
body=body.encode("utf8"), filename=media_set_filename,
)
반환한 미디어는 임시 상태입니다. 객체의 미디어 참조 속성에 넣고 액션이 편집을 적용해야 영구 연결됩니다.
새 객체에 미디어 연결
가상의 Aircraft는 String 기본 키 aircraftId와 미디어 참조 myMediaProperty를 가진다고 가정합니다. Python에서는 my_media_property를 사용합니다.
TSv2 uploadTextToNewPlane.ts는 입력 키로 객체를 만들고 텍스트 파일을 연결하는 편집 목록을 반환합니다.
import type { Client } from "@osdk/client";
import { Aircraft } from "@ontology/sdk";
import { Edits, createEditBatch, uploadMedia } from "@osdk/functions";
export default async function uploadTextToNewPlane(
client: Client, aircraftId: string, body: string
): Promise<Edits.Object<Aircraft>[]> {
const media = await uploadMedia(client, {
data: new Blob([body], { type: "text/plain" }), fileName: "/planes/aircraft.txt",
});
const batch = createEditBatch<Edits.Object<Aircraft>>(client);
batch.create(Aircraft, { aircraftId, myMediaProperty: media });
return batch.getEdits();
}
Python도 생성한 Media를 직접 편집에 넣습니다.
from functions.api import OntologyEdit, function
from ontology_sdk import FoundryClient
from ontology_sdk.ontology.objects import Aircraft
@function(edits=[Aircraft])
def upload_text_to_new_plane(aircraft_id: str, body: str) -> list[OntologyEdit]:
client = FoundryClient()
media = client.ontology.media.upload_media(body=body.encode("utf8"), filename="/planes/aircraft.txt")
edits = client.ontology.edits()
edits.objects.Aircraft.create(aircraft_id, my_media_property=media)
return edits.get_edits()
기존 객체의 편집에 Media를 넣거나 액션의 미디어 참조 매개변수를 함수에 직접 전달할 수도 있습니다.
TypeScript v1의 기존 미디어 연결
TSv1은 함수 안에서 새 미디어 업로드를 지원하지 않습니다. 이미 존재하는 MediaItem을 객체 속성에 지정할 수 있습니다. 미디어 참조 속성이 생성 바인딩에 필요하면 functions.json의 enableMediaReferenceProperties 설정도 확인합니다.
import { Edits, MediaItem, OntologyEditFunction } from "@foundry/functions-api";
import { Aircraft } from "@foundry/ontology-api";
export class MediaEditFunctions {
@Edits(Aircraft)
@OntologyEditFunction()
public setExistingMediaToObject(aircraft: Aircraft, mediaItem: MediaItem): void {
aircraft.myMediaProperty = mediaItem;
}
}
TSv1 바이트, 메타데이터와 타입 가드
MediaItem.readAsync()는 Blob을, getMetadataAsync()는 IMediaMetadata를 반환합니다. 메타데이터를 구분하는 함수는 다음과 같습니다.
- isAudioMetadata, isDicomMetadata, isDocumentMetadata
- isImageryMetadata, isSpreadsheetMetadata, isUntypedMetadata, isVideoMetadata
미디어 자체는 MediaItem.isAudio, isDicom, isDocument, isImagery, isSpreadsheet와 isVideo로 좁힙니다. 예를 들어 이미지 메타데이터를 좁힌 뒤 dimensions의 폭과 높이를 읽습니다.
import { Function, Integer, MediaItem, isImageryMetadata } from "@foundry/functions-api";
export class MediaMetadataFunctions {
@Function()
public async imageWidth(media: MediaItem): Promise<Integer | undefined> {
const metadata = await media.getMetadataAsync();
return isImageryMetadata(metadata) ? metadata.dimensions?.width : undefined;
}
}
TSv1 문서 텍스트와 OCR
기계 생성 PDF는 extractTextAsync로 내장 텍스트를 읽는 편이 OCR보다 빠르고 정확할 수 있습니다. 스캔 PDF처럼 내장 텍스트가 없으면 ocrAsync를 사용합니다.
| 옵션 | 의미 |
|---|---|
| startPage | 0부터 시작하는 포함 시작 페이지 |
| endPage | 0부터 시작하는 제외 끝 페이지 |
| languages, OCR | 인식할 언어 목록. 생략 또는 빈 목록 가능 |
| scripts, OCR | 인식할 문자 체계 목록. 생략 또는 빈 목록 가능 |
| outputType, OCR | text 또는 hocr |
extractTextAsync에서 시작과 끝을 모두 생략하면 모든 페이지의 텍스트 목록을 반환합니다. OCR도 페이지별 문자열 목록을 반환합니다.
가상의 ArxivPaper.mediaReference를 읽는 예제입니다.
import { Function, MediaItem } from "@foundry/functions-api";
import { ArxivPaper } from "@foundry/ontology-api";
export class DocumentFunctions {
@Function()
public async firstPageText(paper: ArxivPaper): Promise<string | undefined> {
const media = paper.mediaReference;
if (media === undefined || !MediaItem.isDocument(media)) return undefined;
return (await media.ocrAsync({ endPage: 1, languages: [], scripts: [], outputType: "text" }))[0];
}
@Function()
public async embeddedText(paper: ArxivPaper): Promise<string[]> {
const media = paper.mediaReference;
if (media === undefined || !MediaItem.isDocument(media)) throw new Error("문서 미디어가 필요합니다.");
return media.extractTextAsync({});
}
}
TSv1 오디오 전사
오디오에 transcribeAsync를 호출할 수 있습니다. language는 TranscriptionLanguage, performanceMode는 TranscriptionPerformanceMode를 사용하며 More Economical과 More Performant 모드가 있습니다.
outputFormat은 plainTextNoSegmentData 또는 pttml입니다. plainTextNoSegmentData에는 addTimestamps Boolean을 지정할 수 있습니다. pttml은 TTML과 유사한 타임드 텍스트 형식입니다.
import { Function, MediaItem, TranscriptionLanguage, TranscriptionPerformanceMode } from "@foundry/functions-api";
import { AudioFile } from "@foundry/ontology-api";
export class AudioFunctions {
@Function()
public async transcribeAudioFile(file: AudioFile): Promise<string | undefined> {
const media = file.mediaReference;
if (media === undefined || !MediaItem.isAudio(media)) return undefined;
return media.transcribeAsync({
language: TranscriptionLanguage.ENGLISH,
performanceMode: TranscriptionPerformanceMode.MORE_ECONOMICAL,
outputFormat: { type: "plainTextNoSegmentData", addTimestamps: true },
});
}
}
TSv2와 Python의 회전, OCR, PDF 렌더링 및 범위 추출은 미디어 변환, 페이지에 인식한 단어 상자를 그리는 작업은 hOCR와 좌표 변환을 따릅니다.