Skip to content

미디어 추출 실전 ​

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

추출 개요 ​

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

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

비디오 추출 (세 개 소스) ​

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

순서소스스캔 대상설명
①원본 HTML 스캔iframe/embed/object의 src/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.Videos와 Result.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* 옵션 ​

PreserveVideos와 PreserveAudios는 Extract 결과에 미디어를 포함할지 제어합니다:

설정 필드기본값동작
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를 꺼도 ExtractAllLinks의 IncludeVideos에 영향을 주지 않으며, 그 반대도 마찬가지입니다. 사용하는 API 에 맞는 옵션을 설정하세요.

TextOnlyConfig 성능 프리셋 ​

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

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

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

다음 단계 ​