GIF 움짤 용량이 상대적으로 크기 때문에 움짤 용량을 줄이기 위해 GIF MP4 변환하는 움짤 gif 변환을 자동으로 할 수 있는 방법을 연구, 테스트해 보고 그 방법을 정리해 공유해 봅니다.
원래는 webp 변환처럼 nginx 웹서버 기능을 활용하는 방법을 시도했지만, img 파일과 동영상 파일의 차이로 인해서 생각보다 복잡해 젔기 때문에 이를 포기하고 편리님이 제공한 간단한 플러그인을 적용하는 것을 정리했습니다.
테스트에 사용한 움짤 gif 이미지
우선 이 테스트에 사용된 GIF 움짤은 요즘 성가를 높이고 있는 블랙빙크의 리사의 아름다움 미소가 돋보이는 움짤 몇가지를 골라 보았습니다.
이 움짤 이미지들은 구글에서 가져온 것이라 지적재산권 문제를 확인해 보고 문제가 된다면 지우도록 하겠습니다.
GIF 움짤 중에서 화질이 좋은 것으로 골랐는데 아무래도 용량 문제가 있다보니 이미지 사이즈가 작은 파일들이 대부분이기는 합니다.
- GIF 움짤 용량 1.5MB, 움짤 사이즈는 498×354
- mp4 동영상으로 전환 시 154k로 거의 10% 수준으로 줄어 듬
- GIF 움짤 용량 8MB, 움짤 사이즈는 498×498
- mp4 동영상으로 전환 시 423k로 거의 50% 수준으로 줄어 듬
- GIF 움짤 용량 2.6MB, 움짤 사이즈는 280×420
- mp4 동영상으로 전환 시 190k로 거의 7% 수준으로 줄어 듬
움짤 gif 동영상 변환 프로그램 설치
먼저 gif mp4 변환이 가능한 동영상 변환 프로그램을 설치합니다. 인터넷을 검색해 보면 금방 알 수 있겠지만 공개용 프로그램으로 FFmpeg을 가장 많이 사용하는 것 같습니다.
우분투 20.04에서 설치하는 방법은 아래와 같습니다.
다행히도 우분투 20.04는 별다를 컴파일없이 바로 apt 명령으로 설치할 수 있네요. 아래 명령 사용하면 매우 단순하게 설치할 수 있습니다. 당연히 먼저 업데이트를 해서 최신 상태로 만들어 놓고 프로그램을 설치합니다.
sudo apt update
sudo apt install ffmpeg
Code language: PHP (php)
이것으로 설치가 끝났다. 그래도 뭐가 미진하니 설치한 버전 정도는 확인해 보시죠.
ffmpeg -version
Code language: PHP (php)
그러면 다음과 같은 메세지를 만날 수 있습니다.
ffmpeg version 4.2.4-1ubuntu0.1 Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 9 (Ubuntu 9.3.0-10ubuntu2)
configuration: --prefix=/usr --extra-version=1ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
libavutil 56. 31.100 / 56. 31.100
libavcodec 58. 54.100 / 58. 54.100
libavformat 58. 29.100 / 58. 29.100
libavdevice 58. 8.100 / 58. 8.100
libavfilter 7. 57.100 / 7. 57.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 5.100 / 5. 5.100
libswresample 3. 5.100 / 3. 5.100
libpostproc 55. 5.100 / 55. 5.100
Code language: PHP (php)
[참] gif를 대체할 동영상 포맷 소개
움직이는 에니메이션 파일인 gif를 대체하는 동영상을 크게 세가지가 있습니다. mp4와 WebM 그리고 Ogg 파일 포맷이 그것들인데요.
gif는 1987년도에 컴퓨서브(CompServe)사에서 개발한 무손실 압축 이미지 포맷입니다. 무손실 압축에서 읽을 수 있다시피 상대적으로 용량이 크고, 색상 표현이 최대 256컬러만 지원하기 때문에 색 왜곡현상이 발생합니다. 그리고 프레임이 늘어날 수록 급격한 용량 증가가 발생합니다.
그렇지만 가장 오랜된 포맷인만큼 지원하지 않는 기기나 브라우저가 없기 때문에 그만큼 많은 사용자를 확보하고 있습니다.
이를 대체하기 위한 mp4와 같은 동영상 포맷은 html5가 등장하면서 <video> 태그가 추가되면서 별도의 설정없이 이러한 파일 포맷을 지원하는 브라우저가 점점 늘고 있습니다.
가장 많은 브라우저가 지원하는 mp4
위에서 정리한 세가지 포맷 중에서 mp4는 점점 더 많은 브라우저가 지원하면서 98%에 가까운 브라우저가 지원하고 있습니다.
전 세계적으로 도대체 얼마나 많은 브라우저가 이 mp4를 지원할까 살펴보니 98% 정도는 지원하네요. 대부분 지원한다고 봐야 할 듯 합니다.
mp4보다 성능이 좋은 WebM 포맷
위에서 이야기한 mp4보다 WebM 비디오 포맷이 더 압축율이 좋다고 합니다. 아쉽게도 이 비디오 포맷을 지원하는 브라우저는 96%정도로 조금 낮네요.
이 파일 포맷은 구글에서 만들었기 때문에 스티브잡스가 이끄는 애플은 오랬동안 이 포맷 지원을 거부해 왔습니다. 최근에는 제한적으로 지원하기 시작했죠.
아래 이미지에서 보는 것처럼 전 세계적으로 95.5% 지원한다고 하지만, 애플 계열은 부분적으로만 지원하기 때문에 완전한 96%라고 하기는 애매합니다.
더구나 우리나라에서 많이 사용하는 IE지원을 하디 않기 때문에 실제적으로는 70%~80%대 브라우저 지원율로 봐야 할 듯합니다.
가장 효울이 높고 오픈 소스인 Ogg
그리고 요즘 새롭게 등장하는 ogg 비디오 포맷은 78% 정도 지원하고 있습니다.
이 포맷은 가장 완전한 오픈소스라 지적재산권과 관련이 없고 성능도 뛰어납니다. 다만 브라우저 지원율이 상대적으로 매우 낮습니다.
자동으로 GIF를 mp4나 WebM으로 변환 재생하는 플러그인
원래는 Nginx에서 자동으로 변환하는 방법을 생각하려 했는데요. 앞에서 설명한대로 몇가지 이슈가 있어서 매우 간단한 플러그인 소개로 대체하겠습니다.
여기서 소개할 플러그인은 편리님이 소개한 방법입니다.
워드프레스 애니메이션 gif 파일을 mp4로 변환하여 출력하기
gif파일을 mp4 및 WebM 파일로 변경 코드
아래 코드를 functions.php 파일로 저장합니다.
<?php
// https://www.php.net/manual/en/function.imagecreatefromgif.php#104473
function isAnimatedGIF($gif) {
if(!($fh = @fopen($gif, 'rb')))
return false;
$count = 0;
//an animated gif contains multiple "frames", with each frame having a
//header made up of:
// * a static 4-byte sequence (\x00\x21\xF9\x04)
// * 4 variable bytes
// * a static 2-byte sequence (\x00\x2C) (some variants may use \x00\x21 ?)
// We read through the file til we reach the end of the file, or we've found
// at least 2 frame headers
while(!feof($fh) && $count < 2) {
$chunk = fread($fh, 1024 * 100); //read 100kb at a time
$count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches);
}
fclose($fh);
return $count > 1;
}
function convert_gif2mp4($content)
{
$images = array();
$upload_info = wp_upload_dir();
$upload_dir = $upload_info['basedir'];
$upload_url = $upload_info['baseurl'];
$pattern = '#<img[^>]*src=[\'"]?(.+\.gif)[\'"]?[^>]*>#i';
preg_match_all($pattern, $content, $matches);
$count = count($matches[1]);
$urls = array();
if ( $count > 0 ) {
for ( $i=0; $i<$count; $i++ ) {
$url = $matches[1][$i];
$url2 = preg_replace('#^https?:#i', '', $url);
if(in_array($url2, $urls))
continue;
$urls[] = $url;
// 로컬 파일인지 체크
if(strpos( $url, $upload_url ) === false)
continue;
// 이미지 경로 설정
$rel_path = str_replace( $upload_url, '', $url);
$img_file = $upload_dir . $rel_path;
// gif 파일인지 체크
if( !is_file($img_file))
continue;
$size = @getimagesize($img_file);
if($size[2] != 1)
continue;
// 애니메이션 gif 체크
if (!isAnimatedGIF($img_file))
continue;
// mp4 파일 생성
$pinfo = pathinfo($img_file);
$mp4 = $pinfo['dirname'].'/'.$pinfo['filename'].'.mp4';
$webm = $pinfo['dirname'].'/'.$pinfo['filename'].'.webm';
$poster = $pinfo['dirname'].'/poster_'.$pinfo['filename'].'.jpg';
if (is_writable($pinfo['dirname']) && !is_file($mp4)) {
try {
$poster = $pinfo['dirname'].'/poster_'.$pinfo['filename'].'.jpg';
$image = @imagecreatefromgif($img_file);
imagejpeg($image, $poster, 90);
@exec('ffmpeg -i '.escapeshellcmd(preg_replace('/[^0-9A-Za-z_\-\.\\\\\/]/i', '', $img_file)).' -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -c:v libx264 -pix_fmt yuv420p -movflags +faststart '.escapeshellcmd(preg_replace('/[^0-9A-Za-z_\-\.\\\\\/]/i', '', $mp4)));
@exec('ffmpeg -i '.escapeshellcmd(preg_replace('/[^0-9A-Za-z_\-\.\\\\\/]/i', '', $img_file)).' -c vp9 -b:v 0 -crf 41 '.escapeshellcmd(preg_replace('/[^0-9A-Za-z_\-\.\\\\\/]/i', '', $webm)));
} catch(Exception $e) {
continue;
}
}
if (is_file($mp4)) {
$video = '<video poster="'.str_replace($upload_dir, $upload_url, $poster).'" autoplay="autoplay" loop="loop" preload="auto" playsinline webkit-playsinline muted>';
if (is_file($webm))
$video .= '<source src="'.str_replace($upload_dir, $upload_url, $webm).'" type="video/webm">';
$video .= '<source src="'.str_replace($upload_dir, $upload_url, $mp4).'" type="video/mp4">';
$video .= '</video>';
$content = str_replace($matches[0][$i], $video, $content);
}
}
}
return $content;
}
Code language: PHP (php)
워드프레스 플러그인 실행 파일
워드프레스에서 이 플러그인을 실행시키는 파일을 gif2mp4.php 파일로 저장합니다.
<?php
/**
* @package Convert GIF to MP4 in Post
* @version 1.0.0
*/
/*
Plugin Name: Convert GIF to MP4 in Post
Plugin URI: https://ncube.net/
Description: This plugin animated gif to mp4 using ffmpeg in post.
Author: chicpro
Version: 1.0.0
Author URI: https://ncube.net/
*/
require ( plugin_dir_path( __FILE__ ) . '/functions.php' );
add_filter ('the_content', 'convert_gif2mp4', 100);
Code language: PHP (php)
워드프레스 플러그인 폴더 만들기
위에서 만든 워드프레스용 두개 파일을 워드프레스 플러그인 폴더에 gif2mp4와 같은 적절한 이름의 폴더를 만들고 여기에 이 두 파일을 복사합니다.
그리고 이 플러그인을 활성화 시킵니다.
참고
서버에서 PNG 이미지 최적화로 사이트 속도 개선 방법
서버에서 JPEG 이미지 최적화로 사이트 속도 개선 방법