Skip to content

CHICPRO

  • Life Log
  • Cycling Log
  • Photo Log
    • Portrait
    • Landscape
    • Flower
    • Etc
  • Coding Log
  • Information

[PHP] HTTP와 PHP를 이용한 html5 video 스트리밍 구현

2014-08-26 by 편리

일단 제목이 무척 거창하다. 필요에 의해서 검색을 하다가 발견한 내용인데 html5에서 지원하는 video 태그를 이용해 비디오 스트리밍을 제공할 때 진행바를 움직이면 일부 브라우저에서 작동이 멈추는 오류가 있어 이를 해결하기 위해 작성한 코드라고 한다. 나도 마침 스트리밍 기능이 필요해서 코드를 사용해봤다.

출처 : Stream videos to HTML5 video container using HTTP & PHP

그런데 나의 경우 위의 코드를 사용했을 때 Header 정보에서 제공하는 Content-Length 정보가 실제 파일 사이즈와 달라 오류가 발생해 동영상 재상이 되지 않는 문제가 있었다. 그래서 Content-Length header 정보를 추가하는 부분의 코드를 약간 수정해서 사용하니 이상없이 동영상이 재생됐다. 수정한 코드는 아래와 같다.

<?php
set_time_limit(0);
include_once('./_common.php');

// Clears the cache and prevent unwanted output
ob_clean();
@ini_set('error_reporting', E_ALL & ~ E_NOTICE);
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 'Off');

// 동영상정보
$sql = " select file from movie_info where mv_id = '$mv_id' ";
$row = sql_fetch($sql);

if(!$row)
    die('동영상정보가 존재하지 않습니다.');


// Stream videos to HTML5 video container using HTTP & PHP
// http://licson.net/post/stream-videos-php/
$file = './data/movie/'.$row['file']; // The media file's location
if(!is_file($file))
    die('파일이 존재하지 않습니다. 사이트 운영자에게 문의해 주십시오.');
$mime = "application/octet-stream"; // The MIME type of the file, this should be replaced with your own.
$size = filesize($file); // The size of the file

// Send the content type header
header('Content-type: ' . $mime);

// Check if it's a HTTP range request
if(isset($_SERVER['HTTP_RANGE'])){
    // Parse the range header to get the byte offset
    $ranges = array_map(
        'intval', // Parse the parts into integer
        explode(
            '-', // The range separator
            substr($_SERVER['HTTP_RANGE'], 6) // Skip the `bytes=` part of the header
        )
    );

    // If the last range param is empty, it means the EOF (End of File)
    if(!$ranges[1]){
        $ranges[1] = $size - 1;
    }

    // Send the appropriate headers
    header('HTTP/1.1 206 Partial Content');
    header('Accept-Ranges: bytes');
    // Content-Length 가 맞지 않는 오류가 발생하여 주석처리 후 아래 코드로 대체
    //header('Content-Length: ' . ($ranges[1] - $ranges[0])); // The size of the range
    header('Content-Length: ' . $size);

    // Send the ranges we offered
    header(
        sprintf(
            'Content-Range: bytes %d-%d/%d', // The header format
            $ranges[0], // The start range
            $ranges[1], // The end range
            $size // Total size of the file
        )
    );

    // It's time to output the file
    $f = fopen($file, 'rb'); // Open the file in binary mode
    $chunkSize = 8192; // The size of each chunk to output

    // Seek to the requested start range
    fseek($f, $ranges[0]);

    // Start outputting the data
    while(true){
        // Check if we have outputted all the data requested
        if(ftell($f) >= $ranges[1]){
            break;
        }

        // Output the data
        echo fread($f, $chunkSize);

        // Flush the buffer immediately
        @ob_flush();
        flush();
    }
}
else {
    // It's not a range request, output the file anyway
    header('Content-Length: ' . $size);

    // Read the file
    @readfile($file);

    // and flush the buffer
    @ob_flush();
    flush();
}
?>

위 코드는 서버에 저장된 파일을 스트리밍해주는 코드일 뿐이며 브라우저에서 동영상을 보여주기 위해서는 아래와 같은 코드를 사용해서 페이지를 작성해줘야 한다.

<video src="http://example.com/movie.php?mv_id=1234" width="720" height="480" controls="controls" preload="none"></video>

이렇게 했을 경우 동영상 파일의 직접적인 URL을 노출하지 않고도 동영상을 사용자에게 보여줄 수 있다. 추가로 MediaElement.js 를 사용하면 좀 더 쉽게 동영상 보기 화면을 만들 수가 있으니 참고하기 바란다.

Post navigation

Previous Post:

샤오미 10400mAh 보조 배터리 구입

Next Post:

내비게이션 업데이트

2 Commments

  1. Kim says:
    2021-02-22 at 14:54

    오류가 난다고 했던 사이즈 부분에서 헤더를 보면 HTTP/1.1 206 Partial Content로 되어있고..
    아이폰이나 일부 기기 또는 브라우져에서 통째로 받지 않고 일정구간을 호출하여 받는 부분이 있는데, 이런 경우에 사이즈를 파일 사이즈로 대체하게되면 실제로 전송되는 사이즈와 맞지 않아 오류가 발생하는 이슈가 있어서.. 요청한 구간의 크기를 헤더로 셋팅해야하는데.. 문제 없던가요?

    1. 편리 says:
      2021-02-22 at 15:27

      안녕하세요.
      2014년도 포스트로 그 당시에는 아이폰을 사용하지 않아서 테스트 자체를 하지 못했습니다.
      최신의 브라우저에서는 오류가 발생할 수도 있을 것 같습니다. 해당 코드는 더 이상 사용하지 않고 있기 때문에 더 이상의 유지보수는 불가능한 점 양해바랍니다.

Comments are closed.

Recent Posts

  • PHP 코드 중간에서 include_path 설정 변경하기
  • 아이폰 키보드 오타 줄이기
  • iPhone 음악 음질 향상 방법
  • Windows 11 업데이트 수동으로 설치하기
  • AWS CLI를 이용하여 S3 파일의 Content-Type 변경
  • 맥 Automator를 이용한 여러 개 App 동시실행
  • 인터넷 접속이 제한된 환경에서 brew 를 이용한 패키지 업데이트
  • Notepad++ NppFTP 플러그인 수동 설치
  • Gitlab CI 에서 Merge Request Approve 여부 체크
  • hidutil 을 이용한 맥키보드 한/영 변경키 변경

Recent Comments

  • 편리 on Notepad++ NppFTP 플러그인 수동 설치
  • paul-j on Notepad++ NppFTP 플러그인 수동 설치
  • YS on Windows 10 iCloud 사진 저장 폴더 변경
  • 편리 on Docker를 이용한 Centos7 + httpd + php 5.4 개발환경 구축
  • Stas on Docker를 이용한 Centos7 + httpd + php 5.4 개발환경 구축
  • 편리 on [PHP] HTTP와 PHP를 이용한 html5 video 스트리밍 구현
  • Kim on [PHP] HTTP와 PHP를 이용한 html5 video 스트리밍 구현
  • 편리 on 워드프레스 애니메이션 gif 파일을 mp4로 변환하여 출력하기
  • 고맙습니다 on 워드프레스 애니메이션 gif 파일을 mp4로 변환하여 출력하기
  • 편리 on PHPMailer를 이용한 이메일 발송

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org
© 2023 CHICPRO | Built using WordPress and SuperbThemes