Skip to content

미디어 추출 실전

텍스트, 이미지, 링크 외에도 라이브러리는 HTML 에서 비디오와 오디오 리소스를 추출할 수 있습니다. 이 가이드는 추출 메커니즘과 필드 의미를 상세히 설명합니다.

추출 개요

Extract를 호출하면, 비디오와 오디오 추출은 DOM 파싱 이후, 콘텐츠 포맷팅 이전에 실행됩니다. 결과는 각각 Result.VideosResult.Audios에 저장됩니다.

text
DOM 파싱 → 비디오 추출 (3소스) → 오디오 추출 (2소스) → 포맷팅 → Result

비디오 추출 (세 개 소스)

비디오 추출은 다음 순서로 실행되며, 각 URL 은 중복 제거되어 반복 수집되지 않습니다:

순서소스스캔 대상설명
원본 HTML 스캔iframe/embed/objectsrc/data 속성안전한 정제 이전에 실행되어, 정제로 제거되는 임베드 태그가 유실되지 않도록 보장
DOM 순회video/iframe/embed/object 요소파싱된 DOM 트리를 순회하며 요소 속성과 <source> 자식 요소를 읽음
정규식 폴백비디오 파일 URLHTML 텍스트 내의 노출된 비디오 링크를 스캔

원본 HTML 을 스캔하는 이유

iframe, embed, object 등의 임베드 태그는 안전한 정제 단계에서 제거될 수 있습니다. 라이브러리는 정제 이전에 원본 HTML 문자열에서 이러한 태그의 미디어 URL 을 먼저 추출하여, 임베드된 비디오가 정제로 인해 유실되지 않도록 보장합니다.

정규식 폴백이 지원하는 비디오 확장자

.mp4  .webm  .ogg  .mov  .avi  .wmv  .flv  .mkv  .m4v  .3gp

정규식은 http:// 또는 https://로 시작하는 완전한 URL 만 매칭하여, 파일명 조각의 오매칭을 방지합니다.

오디오 추출 (두 개 소스)

순서소스스캔 대상설명
DOM 순회audio 요소 및 <source> 자식 요소src 속성 또는 자식 <source>src/type을 읽음
정규식 폴백오디오 파일 URLHTML 텍스트 내의 노출된 오디오 링크를 스캔

정규식 폴백이 지원하는 오디오 확장자

.mp3  .wav  .ogg  .m4a  .aac  .flac  .wma  .opus  .oga

.ogg 확장자가 비디오와 오디오 목록에 모두 나타남

OGG 는 컨테이너 포맷으로, 비디오(Theora) 또는 오디오(Vorbis/Opus)를 담을 수 있습니다. .ogg 확장자의 URL 은 비디오이자 오디오로 감지되어, Result.VideosResult.Audios에 모두 나타날 수 있습니다. 오디오 전용 변형인 .oga는 오디오 목록에만 나타납니다.

필드 상세

VideoInfo

필드타입설명
URLstring비디오 소스 주소
Typestring감지된 타입: MIME 타입 (예: video/mp4) 또는 embed (iframe 이 페이지를 임베드)
Posterstring<video>poster 속성 (포스터 이미지 URL)
Widthstring너비 속성 (원본 문자열, 숫자로 파싱되지 않음)
Heightstring높이 속성 (원본 문자열, 숫자로 파싱되지 않음)
Durationstring재생 시간 속성 (원본 문자열, 숫자로 파싱되지 않음)

AudioInfo

필드타입설명
URLstring오디오 소스 주소
Typestring감지된 타입: MIME 타입 (예: audio/mpeg)
Durationstring재생 시간 속성 (원본 문자열, 숫자로 파싱되지 않음)

Type 필드의 값 규칙

Type은 두 가지 비디오 소스를 구분합니다:

Type 값의미발생 시나리오
embediframe 이 참조하는 비디오 페이지YouTube, Vimeo, Youku, Bilibili 등 임베드형 플레이어
MIME 타입 (예: video/mp4)비디오 파일 컨테이너정규식 폴백으로 매칭된 노출 URL, 또는 <source type="..."> 속성값
빈 문자열타입을 감지하지 못함<video src="...">로 직접 소스를 지정 (<source> 자식 요소가 없을 때)

embed 감지를 지원하는 임베드 플랫폼:

플랫폼URL 패턴
YouTubeyoutube.com/embed/, youtube-nocookie.com/embed/
Vimeoplayer.vimeo.com/video/
Dailymotiondailymotion.com/embed/
Youkuplayer.youku.com/
Tencent Videov.qq.com/
Bilibilibilibili.com/

완전한 예제

go
package main

import (
    "fmt"
    "log"

    "github.com/cybergodev/html"
)

func main() {
    // 3가지 미디어 시나리오를 포함한 HTML:
    // 1. iframe YouTube 임베드 (Type = "embed")
    // 2. <source> 자식 요소가 있는 네이티브 비디오 (Type은 type 속성에서)
    // 3. <source> 자식 요소가 있는 오디오 (Type은 type 속성에서)
    data := []byte(`<html><body><article>
        <h1>멀티미디어 페이지</h1>
        <p>이 문서는 비디오와 오디오 기술을 소개합니다.</p>
        <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" width="560" height="315"></iframe>
        <video poster="poster.jpg" width="640" height="360">
            <source src="https://example.com/trailer.mp4" type="video/mp4">
        </video>
        <audio>
            <source src="https://example.com/episode.mp3" type="audio/mpeg">
        </audio>
    </article></body></html>`)

    result, err := html.Extract(data)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("비디오 수: %d\n", len(result.Videos))
    // 비디오 수: 2

    for i, v := range result.Videos {
        fmt.Printf("  비디오 %d: %s\n", i+1, v.URL)
        fmt.Printf("    Type: %s", v.Type)
        if v.Poster != "" {
            fmt.Printf(", 포스터: %s", v.Poster)
        }
        if v.Width != "" || v.Height != "" {
            fmt.Printf(", 크기: %sx%s", v.Width, v.Height)
        }
        fmt.Println()
    }
    // 비디오 1: https://www.youtube.com/embed/dQw4w9WgXcQ
    //   Type: embed, 크기: 560x315
    // 비디오 2: https://example.com/trailer.mp4
    //   Type: video/mp4, 포스터: poster.jpg, 크기: 640x360

    fmt.Printf("\n오디오 수: %d\n", len(result.Audios))
    // 오디오 수: 1

    for i, a := range result.Audios {
        fmt.Printf("  오디오 %d: %s (Type: %s)\n", i+1, a.URL, a.Type)
    }
    // 오디오 1: https://example.com/episode.mp3 (Type: audio/mpeg)
}

설정 제어

Preserve* 옵션

PreserveVideosPreserveAudiosExtract 결과에 미디어를 포함할지 제어합니다:

설정 필드기본값동작
PreserveVideostruefalse일 때 Result.Videos가 빈 슬라이스가 됨
PreserveAudiostruefalse일 때 Result.Audios가 빈 슬라이스가 됨
go
cfg := html.DefaultConfig()

// 비디오와 오디오 추출 비활성화 (텍스트, 이미지, 링크만 유지)
cfg.PreserveVideos = false
cfg.PreserveAudios = false

result, err := html.Extract(data, cfg)
// result.Videos → []
// result.Audios → []

Preserve* 와 Include* 의 차이

두 설정 그룹은 독립적으로 동작하며, 서로 다른 API 를 제어합니다:

설정 그룹제어하는 API설명
PreserveVideos/PreserveAudiosExtractResult.Videos/Result.Audios의 채움 여부 제어
IncludeVideos/IncludeAudiosExtractAllLinks링크 열거에 비디오/오디오 URL 포함 여부 제어

두 설정은 독립적

PreserveVideos를 꺼도 ExtractAllLinksIncludeVideos에 영향을 주지 않으며, 그 반대도 마찬가지입니다. 사용하는 API 에 맞는 옵션을 설정하세요.

TextOnlyConfig 성능 프리셋

텍스트만 필요할 때, TextOnlyConfig()는 모든 Preserve* 옵션을 이미 비활성화하므로 수동 설정이 불필요합니다:

go
cfg := html.TextOnlyConfig()
// PreserveImages = false
// PreserveLinks = false
// PreserveVideos = false
// PreserveAudios = false

result, err := html.Extract(data, cfg)
// 모든 미디어 추출을 건너뛰고 최적의 성능

다음 단계