워드프레스 애니메이션 gif 파일을 mp4로 변환하여 출력하기
최근에 애니메이션 gif 파일을 mp4로 변경해서 출력하는 게 유행(?)이라고 할까? 포스팅 때 애니메이션 gif 파일을 첨부하지는 않기 때문에 굳이 관심을 가져야 할 이유가 없었는데.. 오늘은 왠지 한번 해볼까? 하는 생각이 들어서 기본 기능만 작동하도록 플러그인을 만들어 봤다. 개발 환경은 아래와 같다.
- WordPress : 5.5
- PHP : 7.4.9
- ffmpeg : 4.2.4
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;
}
워드프레스 플러그인 적용을 위한 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://chicpro.dev/
Description: This plugin animated gif to mp4 using ffmpeg in post.
Author: chicpro
Version: 1.0.0
Author URI: https://chicpro.dev/
*/
require ( plugin_dir_path( __FILE__ ) . '/functions.php' );
add_filter ('the_content', 'convert_gif2mp4', 100);
위 두개의 파일을 wp-content > plugins 폴더 안에 gif2mp4 와같은 폴더를 생성한 후 그 안에 넣어준다. 그런 다음 워드프레스 관리자 페이지에서 플러그인을 활성해 주면 된다. 포스트 내용에 gif 파일이 출력되는 코드에 따라 $pattern = '#<img[^>]*src=[\'"]?(.+\.gif)[\'"]?[^>]*>#i';
이 부분을 적당히 수정해야 할 수도 있다. 전체 코드는 github 에서 다운로드 할 수 있다.
github repo : https://github.com/chicpro/wordpress-gif2mp4
완전 좋아요!
mp4와 webm을 동시에 지원하는 개념이 정말 좋은 것 같습니다.
선택해서 보여주는 걸까요?
아마 기기에 따라서 선택되어 재생이 될 것으로 생각됩니다.
외국 쪽 자료에서는 mp4와 webm을 동시에 지원하는 게 많습니다.
혹시 그누보드도 가능할까요?
이미 thisgun님의 https://sir.kr/g5_plugin/7476 플러그인도 있지만
webm은 지원이 안더라구요.
그누보드에서 webm까지 한꺼번에 지원되면 정말 좋을 것 같습니다.
어떤 부분을 바꾸면 될까요?
요즘 그누보드 작업이 별로 없어서요.. ^^;
근데.. 이미 수정하신 것 같네요. ㅎㅎ
참고해서 그누보드 5.4용 플러그인을 수정해보았습니다.
그런데 출력할 때
if (is_file($webm))
이 부분은 그누보드에서 어떻게 처리해야될지 모르겠습니다.
일단 그냥 if 부분없이 다 출력되도록 했거든요.
그러니 정상적으로 소스에 webm과 mp4가 둘다 들어갔습니다.
if webm 부분은 왜 넣었을까요?
gif 중에 webm 생성이 안되는 파일이 있는건가요?
음.. 저는 거의 습관적으로 파일 유무를 체크하는 것 같습니다.
테스트 중 webm 파일이 생성되지 않은 경우는 없지만..
오류라는 건 언제 발생할지 모르니까요..
일단 webm과 mp4를 동시에 출력이 되게 설정했습니다.
플러그인을 수정해서 그누보드 플러그인에 올려도 되겠죠? ^^;;;
감사합니다.
제 코드가 조금이라도 도움이 됐다면.. 그걸로 만족합니다. 감사합니다.
안녕하세요 소중한 자료 감사합니다
다름이 아니라 제가 word press 에서 귀하의 파일 적용해서 잘 테스트 하고,
갑자기 서버 이전할 일이 생겨 백업 후 서버 옮겼더니 안되네요….
전 서버에서는 잘 되었는데,,, 혹시 권한 문제인거 같기도 한데
퍼미션 설정을 제가 놓친게 있을까요
아니면 제가 뭔가 큰 걸 놓치고 있는걸까요 ㅠㅠ
고견 기다립니다
안녕하세요.
먼저 확인해 보셔야할 것이 ffmpeg 패키지가 설치되어 있는지.. php 에서 exec 명령어는 사용이 가능한지 등 입니다. ffmpeg 등이 설치되어 있는데도 파일이 생성되지 않는다면 퍼미션 부분일텐데요.. 쓰기 권한이 있는지 확인해 보셔야할 것으로 생각됩니다.
ffmpeg 패키지라는게 정확히 어떤건지 궁금합니다. 워드프레스에 적용했는데 gif가 변환되어 나오지 않아서 뭐가 문제인지 모르겠네요.
안녕하세요.
ffmpeg는 오픈소스 동영상 처리 패키지라고 하면 될 것 같습니다. 해당 패키지가 서버에 설치되어 있지 않으면 영상으로 변환되지 않습니다.