×

注意!页面内容来自https://github.com/SomeBottle/PicVid,本站不储存任何内容,为了更好的阅读体验进行在线解析,若有广告出现,请及时反馈。若您觉得侵犯了您的利益,请通知我们进行删除,然后访问 原网页

Skip to content
<> /* Override primer focus outline color for marketing header dropdown links for better contrast */ [data-color-mode="light"] .HeaderMenu-dropdown-link:focus-visible, [data-color-mode="light"] .HeaderMenu-trailing-link a:focus-visible { outline-color: var(--color-accent-fg); }

SomeBottle/PicVid

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PicVid

A simple PHP script that hides video data within image files.

Demo

Using a hook based on Hls loader:

Using EXT-X-BYTERANGE option in m3u8 file:

AliExpress image hosting has adopted a strategy of converting images to the webp formatso the previous demo based on AliExpress image hosting is no longer functional. The demo has now been migrated to Gitee Pages for learning and reference purposes only. (Video loading may be slightly slow).

Thanks to

Requirements

  • Allow PHP function: shell_exec
  • Install and correctly configure ffmpeg's environment variables.

Config

Edit pv.php:

$output_dir = 'output';  /*output directory(based on the location of pv.php)*/  
$if_windows = true;  /*whether you are using Windows*/  
$clearLogOnStart = true;  /*clear executeLog.log when running the script*/  
$maxTSFileSize = 5242880; /*(In bytes) Maximum size of each split out ts file (more than that will be compressed) */  
$mergeTSUpTo = 2097152; /*(In bytes,cannot be set over $maxTSFileSize) The max ts file size generated when merging several small ts files*/  
$disguisePic = __DIR__ . '/small.png'; /*The picture used for disguisingwe suggest using a jpg or png file*/  
$exitBigTSNum = 0.50; /*(×100%)When large(>$maxTSFileSize) ts files' total num account for more than $exitBigTSNumthe script will exit and recommend you to use -recomp*/
$useByteRange = true; /*Will you use the BYTERANGE option in the generated m3u8 fileyou can also use '--nobr' to disable it in the command line*/

Edit uploadAPI.php:

/*PV.PHP UPLOAD PICthe first return value:<pic url> or <bool:false> in stand of error*/
function PVUpload($path){
	//pic upload function
	$rawdata=
	$imgurl=
	return [(empty($imgurl) ? false : $imgurl),$rawdata];
}   

You should write your own function that uploads pics to the picbed through the picbed's API.

  • $path is the absolute path of the file which is to be uploaded.
  • $rawdata is the raw response that picbed's API returns in many cases it is in JSON format.
  • $imgurl is the url of the uploaded pic usually it is contained in $rawdata.
  • There are 2 values in return: the first one is the url of the uploaded pic the second one is rawdata. When error occurs during uploadingthe first value should be set to false.

for example if you make a function upload($path) to upload each picture and it returns with the JSON below:

{"code":0,"data":{"size":"264","url":"https://s1.ax1x.com/2020/09/16/wgnGxf.png"}}  

then:

/*PV.PHP UPLOAD PICthe first return value:<pic url> or <bool:false> in stand of error*/
function PVUpload($path){
	//pic upload function
	$rawdata=upload($path);
	$parsed_data=on_decode($rawdata,true);
	$imgurl=$parsed_data['data']['url'];
	return [(empty($imgurl) ? false : $imgurl),$rawdata];
}   

Bypass uploading

By defaultpv.php will upload the disguised pics to picbeds through uploadAPI.php.

If you want to bypass the upload processand just save these pics to localyou can use pv_bypass_upload.php and saveToLocal.php instead.

In this wayyour directory structure will be as follows:

YourDir
├── executeLog.log # ffmpeg output logs
├── output # output directory
│   ├── 0.ts # ts files
│   ├── 1.ts
│   ├── pics # disguised pictures you saved
│   │   ├── temppic1440-0.jpg
│   │   └── temppic999-1.jpg
│   ├── video.m3u8.jpg # m3u8 file disguised in jpg
│   └── video.real.m3u8 # m3u8 file without disguise (recommend)
├── potato.jpg # disguising picture
├── pv_bypass_upload.php 
├── rick.mp4 # original video
└── saveToLocal.php # required by pv_bypass_upload.php

You may want to upload those pics to picbeds manuallyand the URLs in m3u8 file need to be updated.

Fortunatelyyou will be asked to type in the URL of the parent directory of the place you would like to upload the disguised pictures.

The prompt will look like this:

Example: If you are to upload pic.png to https://example.com/abc/pic.png
You should type in 'https://example.com/abc/'
Please input the parent URL of the pics to be uploaded: https://test/

Preview: Pic test.png corresponds to https://test/test.png
Type in 'yes' to confirm: yes
OK.

In the example aboveI use https://test/ as the parent URLand the generated m3u8 file will look like this:

...
#EXTINF:10.08,
#EXT-X-BYTERANGE:3408252@3610
https://test/temppic941-0.jpg
...

If I leave the input blankthe generated m3u8 file will be as follows:

...
#EXTINF:10.08,
#EXT-X-BYTERANGE:3408252@3610
temppic941-0.jpg
...

Usage

Type at the command line: php <pv.php|pv_bypass_upload.php> [--nobr] [--recomp] -v videofile

  • I suggest you delete all of the files in the output folder before running the script.
  • Maybe only available for x264 encoded video now.
  • Video file is in the same directory as pv.php
  • The script will automatically compress large TS Files through FFmpeg's crf option.
  • If you use the option --nobr it won't use EXT-X-BYTERANGE option in the generated m3u8 file.
  • If you use the option --recomp it will try to re-encode your original video in order to make it easier to be split.
  • If you used --recomp and still get a TS compression failure ,please compress the video file by yourselfor change the config item $maxTSFileSize.

Notice

  • If space exists in the absolute path where pv.php lies it may return "Video bitrate get failed" error.

How to play

  • Use Hls. also you can take a look at the demo.
  • After running the script you will get two files in the output folder: video.real.m3u8 and video.m3u8.<suffix of disguise pic>

On the one hand(Not suggested)

Assume that your disguise pic's suffix is .png,and you've got video.m3u8.png in the output folder. With hls. you can write like this:

 var video = document.getElementById('video');
  var videoSrc = 'video.m3u8.png';
  var config = {
	  debug:true
  };
  (function (Hls, offset) {
    var load = Hls.DefaultConfig.loader.prototype.load;
    Hls.DefaultConfig.loader.prototype.load = function (context, config, callbacks) {
        if (context.type === 'manifest' || context.type === 'level' || context.responseType === 'arraybuffer') {
            var onSuccess = callbacks.onSuccess;
            callbacks.onSuccess = function (response, stats, context) {
                // .m3u8文件载入时不要给截取了
                if (response.url.endsWith('.m3u8')) return onSuccess.call(this, response, stats, context);
                response.data = response.data.slice(offset);
                return onSuccess.call(this, response, stats, context);
            };
        }
        return load.call(this, context, config, callbacks);
    }
  })(Hls, 69); // Video bytes start from pos 69
 if (Hls.isSupported()) {
    var hls = new Hls(config);
    hls.loadSource(videoSrc);
    hls.attachMedia(video);
  }else{
    //not supported
  }  

By using a custom loader which helps you ignore the picture in front of the m3u8 fileyou can play the video successfully.Howeverdue to the nonsupport of Media Source Extension on iOS Safariyou can't even load it in iOS Safari.

On the other hand

⚠️ Currently not working without EXT-X-BYTERANGEyou need to set $useByteRange = true; in the config so as to play in this way.


Just put aside video.m3u8.png and take a look at video.real.m3u8you just need to delete the hook code of Hls and add codes to make it alternative for natively m3u8 support browser(Such as Safari):

 var video = document.getElementById('video');
  var videoSrc = 'video.real.m3u8';
  var config = {
	  debug:true
  };
 if (Hls.isSupported()) {
    var hls = new Hls(config);
    hls.loadSource(videoSrc);
    hls.attachMedia(video);
  }else{
    video.src = videoSrc;
    alert('你的浏览器自带支持m3u8,如果无法播放请发issue\nYour browser natively support m3u8 playingcreate issue if it doesn\'t work.');  
  }  

In this wayyour video is available in almost all of the main stream web browser.

Additional notice

  • Due to the security policy of the web browser you won't able to play disguised videos if the picbed has a restriction on CORS policy.

Special thanks

  • Shota for feedbacking the problem in Safari.
  • Ohmyga and Yueer for helping test the new ways.

MIT License.

About

A simple PHP script that hides video data within image files.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages