php-ffmpeg 中文版使用功能介绍-程序员宅基地

技术标签: php-ffmpeg  ffmpeg功能介绍  php扩展库  ffmpeg  中文版  

php-ffmpeg

面向对象的库,可使用FFmpeg / AVConv转换视频/音频文件。

查看另一个惊人的: PHP FFMpeg extras, 您将在其中找到许多音频/视频格式。

请注意

该库如何工作:

该库需要有效的FFMpeg安装。您将需要FFMpeg和FFProbe二进制文件才能使用它。确保可以使用系统PATH找到这些二进制文件,以获取二进制文件检测的好处,否则,您必须在加载时显式给出二进制文件路径。

对于Windows用户:请在http://ffmpeg.zeranoe.com/builds/中找到二进制文件。

已知的问题:

  • Using rotate and resize will produce a corrupted output when using
    libav 0.8. 使用rotate和resize将产生损坏的输出 。该错误已在版本9中修复。此错误未在最新的ffmpeg版本中出现。

安装

推荐的安装PHP-FFMpeg的方法是通过 Composer.

$ composer require php-ffmpeg/php-ffmpeg

基本用法


require 'vendor/autoload.php';

$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open('video.mpg');
$video
    ->filters()
    ->resize(new FFMpeg\Coordinate\Dimension(320, 240))
    ->synchronize();
$video
    ->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10))
    ->save('frame.jpg');
$video
    ->save(new FFMpeg\Format\Video\X264(), 'export-x264.mp4')
    ->save(new FFMpeg\Format\Video\WMV(), 'export-wmv.wmv')
    ->save(new FFMpeg\Format\Video\WebM(), 'export-webm.webm');

文献资料

本文档是发现API的简介。建议浏览源代码,因为它是自记录的。

FFMpeg

FFMpeg\FFMpeg是用来操纵媒体的主要对象。要构建它,请使用static FFMpeg\FFMpeg::create:

$ffmpeg = FFMpeg\FFMpeg::create();

FFMpeg将自动检测ffmpeg和ffprobe二进制文件。如果要显式给出二进制路径,则可以将数组作为配置传递。Psr\Logger\LoggerInterface 也可以传递A 来记录二进制执行。

$ffmpeg = FFMpeg\FFMpeg::create(array(
    'ffmpeg.binaries'  => '/opt/local/ffmpeg/bin/ffmpeg',
    'ffprobe.binaries' => '/opt/local/ffmpeg/bin/ffprobe',
    'timeout'          => 3600, //基础进程的超时
    'ffmpeg.threads'   => 12,   // FFMpeg应该使用的线程数
), $logger);

操纵媒体

FFMpeg\FFMpeg根据URI创建媒体。URI可以是指向本地文件系统资源,HTTP资源或FFmpeg支持的任何资源的指针。

注意: 要列出FFmpeg构建的所有受支持资源类型,请使用以下
-protocols command:

ffmpeg -protocols

若要打开资源,请使用 FFMpeg\FFMpeg::open 方法.

$ffmpeg->open('video.mpeg');

可以解决两种类型的媒体: FFMpeg\Media\Audio and FFMpeg\Media\Video.
A third type, FFMpeg\Media\Frame, 可以通过视频获得第三种类型。

Video

FFMpeg\Media\Video 可以进行代码转换,即:更改编解码器,隔离音频或视频。可以提取帧。

转码

您可以使用FFMpeg\Media\Video:save方法对视频进行转码。您将FFMpeg\Format\FormatInterface为此通过。

请注意,音频和视频比特率是在格式上设置的。

$format = new FFMpeg\Format\Video\X264();
$format->on('progress', function ($video, $format, $percentage) {
    
    echo "$percentage % transcoded";
});

$format
    ->setKiloBitrate(1000)
    ->setAudioChannels(2)
    ->setAudioKiloBitrate(256);

$video->save($format, 'video.avi');

可以实时监视转码进度,有关更多信息,请参见下面的“格式”文档。

提取图像

您可以使用FFMpeg\Media\Video::frame 方法在任何时间码上提取帧。

该代码返回FFMpeg\Media\Frame与第二个42对应的实例。您可以将任何FFMpeg\Coordinate\TimeCodeas作为参数传递,有关更多信息,请参见下面的专用文档。

$frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(42));
$frame->save('image.jpg');

如果要从视频中提取多个图像,可以使用以下过滤器:

$video
    ->filters()
    ->extractMultipleFrames(FFMpeg\Filters\Video\ExtractMultipleFramesFilter::FRAMERATE_EVERY_10SEC, '/path/to/destination/folder/')
    ->synchronize();

$video
    ->save(new FFMpeg\Format\Video\X264(), '/path/to/new/file');

默认情况下,这会将帧另存为jpg图像。

您可以使用setFrameFileType将帧保存为另一种格式来覆盖此设置:

$frameFileType = 'jpg'; // either 'jpg', 'jpeg' or 'png'
$filter = new ExtractMultipleFramesFilter($frameRate, $destinationFolder);
$filter->setFrameFileType($frameFileType);

$video->addFilter($filter);
Clip

在所需的位置剪切视频。使用输入查找方法。它比使用滤镜剪辑更快。

$clip = $video->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(30), FFMpeg\Coordinate\TimeCode::fromSeconds(15));
$clip->save(new FFMpeg\Format\Video\X264(), 'video.avi');

剪辑过滤器采用两个参数:

  • $start, an instance of FFMpeg\Coordinate\TimeCode, 指定剪辑的起点
  • $duration, optional, an instance of FFMpeg\Coordinate\TimeCode, 指定剪辑的持续时间

在剪辑上,您可以应用与视频相同的过滤器。例如调整大小的过滤器。

$clip = $video->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(30), FFMpeg\Coordinate\TimeCode::fromSeconds(15));
$clip->filters()->resize(new FFMpeg\Coordinate\Dimension(320, 240), FFMpeg\Filters\Video\ResizeFilter::RESIZEMODE_INSET, true);
$clip->save(new FFMpeg\Format\Video\X264(), 'video.avi');
产生波形

您可以使用该FFMpeg\Media\Audio::waveform 方法生成音频文件的波形。

此代码返回一个FFMpeg\Media\Waveform实例。您可以选择将尺寸作为前两个参数以及ffmpeg用于波形的十六进制字符串颜色数组进行传递,有关更多信息,请参见下面的专用文档。

输出文件必须使用PNG扩展名。

$waveform = $audio->waveform(640, 120, array('#00FF00'));
$waveform->save('waveform.png');

如果要从视频中获取波形,请先将其转换为音频文件。

//打开视频文件
$video = $ffmpeg->open( 'video.mp4' );

//设置音频格式
$audio_format = new FFMpeg\Format\Audio\Mp3();

//提取音频到一个新文件为MP3 
$video->save($audio_format, 'audio.mp3');

//设置音频文件
$audio = $ffmpeg->open( 'audio.mp3' );

//创建波形
$waveform = $audio->waveform();
$waveform->save( 'waveform.png' );
筛选器

您可以在应用滤镜FFMpeg\Media\Video与FFMpeg\Media\Video::addFilter 方法。视频接受音频和视频过滤器。

您可以构建自己的过滤器,一些过滤器捆绑在PHP-FFMpeg中-可通过该FFMpeg\Media\Video::filters方法访问它们。

过滤器可链接

$video
    ->filters()
    ->resize($dimension, $mode, $useStandards)
    ->framerate($framerate, $gop)
    ->synchronize();
旋转

将视频旋转到给定角度。

$video->filters()->rotate($angle);

该$angle参数必须是以下常量之一:

  • FFMpeg\Filters\Video\RotateFilter::ROTATE_90: 90° clockwise
  • FFMpeg\Filters\Video\RotateFilter::ROTATE_180: 180°
  • FFMpeg\Filters\Video\RotateFilter::ROTATE_270: 90° counterclockwise
调整大小

将视频调整为给定尺寸。

$video->filters()->resize($dimension, $mode, $useStandards);

调整大小过滤器采用三个参数:

  • $dimension, an instance of FFMpeg\Coordinate\Dimension
  • $mode, one of the constants FFMpeg\Filters\Video\ResizeFilter::RESIZEMODE_* constants
  • $useStandards, 一个布尔值,用于强制使用最接近的宽高比标准。

如果您要使用非标准比例的视频,则可以使用填充滤镜将视频调整为所需大小,然后将其包裹在黑条中。

$video->filters()->pad($dimension);

Pad滤波器采用一个参数:

  • $dimension, an instance of FFMpeg\Coordinate\Dimension

不要忘了以后保存它。

$video->save(new FFMpeg\Format\Video\X264(), $new_file);
水印

使用给定图像对视频加水印。

$video
    ->filters()
    ->watermark($watermarkPath, array(
        'position' => 'relative',
        'bottom' => 50,
        'right' => 50,
    ));

水印过滤器采用两个参数:

$watermarkPath, 即水印文件的路径
$coordinates, 一个数组,定义您希望水印如何定位。您可以使用上述相对定位或绝对定位:

$video
    ->filters()
    ->watermark($watermarkPath, array(
        'position' => 'absolute',
        'x' => 1180,
        'y' => 620,
    ));
帧率

更改视频的帧频。

$video->filters()->framerate($framerate, $gop);

帧率过滤器采用两个参数:

  • $framerate, an instance of FFMpeg\Coordinate\Framerate
  • $gop, a GOP value (integer)
同步化

同步音频和视频。

一些容器可能会使用延迟,导致输出不同步。该过滤器解决了这个问题。

$video->filters()->synchronize();

在所需的位置剪切视频。

$video->filters()->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(30), FFMpeg\Coordinate\TimeCode::fromSeconds(15));

剪辑过滤器采用两个参数:

  • $start, an instance of FFMpeg\Coordinate\TimeCode, 指定剪辑的起点
  • $duration, optional, an instance of FFMpeg\Coordinate\TimeCode, 指定剪辑的持续时间
作物

根据宽度和高度裁剪视频(a Point)

$video->filters()->crop(new FFMpeg\Coordinate\Point("t*100", 0, true), new FFMpeg\Coordinate\Dimension(200, 600));

它带有两个参数:

  • $point, an instance of FFMpeg\Coordinate\Point, 指定要裁剪的点
  • $dimension, an instance of FFMpeg\Coordinate\Dimension, 指定输出视频的尺寸

Audio

FFMpeg\Media\Audio 也可以进行转码,即:更改编解码器,隔离音频或视频。可以提取帧。

转码

您可以使用 FFMpeg\Media\Audio:save 方法对音频进行转码。您将FFMpeg\Format\FormatInterface为此通过。

请注意,音频千比特率是在音频格式上设置的。

$ffmpeg = FFMpeg\FFMpeg::create();
$audio = $ffmpeg->open('track.mp3');

$format = new FFMpeg\Format\Audio\Flac();
$format->on('progress', function ($audio, $format, $percentage) {
    
    echo "$percentage % transcoded";
});

$format
    ->setAudioChannels(2)
    ->setAudioKiloBitrate(256);

$audio->save($format, 'track.flac');

可以实时监视转码进度,有关更多信息,请参见下面的“格式”文档。

筛选器

您可以在应用滤镜 FFMpeg\Media\Audio with the FFMpeg\Media\Audio::addFilter
方法。它仅接受音频过滤器。

您可以构建自己的过滤器,一些过滤器捆绑在PHP-FFMpeg中-可通过该FFMpeg\Media\Audio::filters方法访问它们。

剪裁

在所需的位置剪切音频

$audio->filters()->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(30), FFMpeg\Coordinate\TimeCode::fromSeconds(15));
元数据

将元数据添加到音频文件。只需传递要添加的所有元数据的键=值对的数组即可。如果没有将参数传递到过滤器中,则所有元数据将从输入文件中删除。当前支持的数据是标题,艺术家,专辑,艺术家,作曲家,曲目,年份,描述,插图

$audio->filters()->addMetadata(["title" => "Some Title", "track" => 1]);

//从音频文件中删除所有元数据和视频流
$audio->filters()->addMetadata();

将图稿添加到音频文件

$audio->filters()->addMetadata(["artwork" => "/path/to/image/file.jpg"]);

注意:目前,ffmpeg(版本3.2.2)仅支持输出.mp3文件的图稿

重采样

重新采样音频文件

$audio->filters()->resample($rate);

重采样过滤器具有两个参数:

  • $rate, 有效的音频采样率值(整数)

帧是视频时间码上的图像;请参阅上面有关帧提取的文档。

您可以使用该 FFMpeg\Media\Frame::save 方法保存帧。

$frame->save('target.jpg');

此方法具有第二个可选的布尔参数。将其设置为true以获取准确的图像;执行需要更多时间。

Gif

gif是从视频序列中提取的动画图像。

您可以使用该FFMpeg\Media\Gif::save方法保存gif文件。

$video = $ffmpeg->open( '/path/to/video' );
$video
    ->gif(FFMpeg\Coordinate\TimeCode::fromSeconds(2), new FFMpeg\Coordinate\Dimension(640, 480), 3)
    ->save($new_file);

此方法具有第三个可选的布尔参数,它是动画的持续时间。如果未设置,则会得到固定的gif图像。

级联

此功能使您可以基于多个来源生成一个音频或视频文件。

根据来源的编解码器,有两种连接视频的方法。如果所有源都使用相同的编解码器编码,则您将希望使用FFMpeg\Media\Concatenate::saveFromSameCodecs具有更好性能的。如果您的来源已使用不同的编解码器进行编码,则需要使用FFMpeg\Media\Concatenate::saveFromDifferentCodecs。

第一个功能将使用初始编解码器作为生成文件的编解码器。使用第二个功能,您将能够为生成的文件选择所需的编解码器。

您还需要注意一个事实,当使用saveFromDifferentCodecs方法时,您的文件必须具有视频和音频流。

在这两种情况下,您都必须提供文件数组。

要连接使用相同编解码器编码的视频,请执行以下操作:

// 为了实例化视频对象,您必须传递路径到有效的视频文件。
// 我们建议您将要在此串联中使用的任何视频的路径放在此处。
$video = $ffmpeg->open( '/path/to/video' );
$video
    ->concat(array('/path/to/video1', '/path/to/video2'))
    ->saveFromSameCodecs('/path/to/new_file', TRUE);

保存功能的布尔参数使您可以使用copy参数,该参数可以大大加速编码文件的生成。

要连接使用相同编解码器编码的视频,请执行以下操作:

// 为了实例化视频对象,您必须传递路径到有效的视频文件。
// 我们建议您将要在此串联中使用的任何视频的路径放在此处。
$video = $ffmpeg->open( '/path/to/video' );

$format = new FFMpeg\Format\Video\X264();
$format->setAudioCodec("libmp3lame");

$video
    ->concat(array('/path/to/video1', '/path/to/video2'))
    ->saveFromDifferentCodecs($format, '/path/to/new_file');

有关FFMPEG中级联的更多详细信息,请参见 here, here and here.

格式

格式实现FFMpeg\Format\FormatInterface。若要保存到视频文件,请使
FFMpeg\Format\VideoInterface, 和 FFMpeg\Format\AudioInterface 用于音频文件。

格式也可以扩展 FFMpeg\Format\ProgressableInterface 以获取有关转码的实时信息。

预定义的格式已将进度信息作为事件提供。

$format = new FFMpeg\Format\Video\X264();
$format->on('progress', function ($video, $format, $percentage) {
    
    echo "$percentage % transcoded";
});

$video->save($format, 'video.avi');

为事件提供的回调可以是任何可调用的。

添加其他参数

您可以根据视频格式向编码请求中添加其他参数。

setAdditionalParameters方法的参数是一个数组。

$format = new FFMpeg\Format\Video\X264();
$format->setAdditionalParameters(array('foo', 'bar'));
$video->save($format, 'video.avi');
添加初始参数

您还可以根据视频格式向编码请求中添加初始参数。在覆盖FFMpeg中的默认输入编解码器时,这可能特别方便。

setInitialParameters方法的参数是一个数组。

$format = new FFMpeg\Format\Video\X264();
$format->setInitialParameters(array('-acodec', 'libopus'));
$video->save($format, 'video.avi');
创建自己的格式

创建格式的最简单方法是扩展摘要 FFMpeg\Format\Video\DefaultVideo和FFMpeg\Format\Audio\DefaultAudio。并实现以下方法。

class CustomWMVFormat extends FFMpeg\Format\Video\DefaultVideo
{
    
    public function __construct($audioCodec = 'wmav2', $videoCodec = 'wmv2')
    {
    
        $this
            ->setAudioCodec($audioCodec)
            ->setVideoCodec($videoCodec);
    }

    public function supportBFrames()
    {
    
        return false;
    }

    public function getAvailableAudioCodecs()
    {
    
        return array('wmav2');
    }

    public function getAvailableVideoCodecs()
    {
    
        return array('wmv2');
    }
}
座标

FFMpeg使用许多单位进行时间和空间坐标。

  • FFMpeg\Coordinate\AspectRatio 代表长宽比。
  • FFMpeg\Coordinate\Dimension 代表一个维度。
  • FFMpeg\Coordinate\FrameRate 代表帧率。
  • FFMpeg\Coordinate\Point 代表一个观点。(自v0.10.0起支持动态点)
  • FFMpeg\Coordinate\TimeCode 代表时间码。

FFProbe

FFMpeg\FFProbe 在内部 FFMpeg\FFMpeg 用于检测媒体。您也可以使用它来提取媒体元数据。

$ffprobe = FFMpeg\FFProbe::create();
$ffprobe
    ->streams('/path/to/video/mp4') //提取流信息
    ->videos()                      //过滤视频流
    ->first()                       //返回第一个视频流
    ->get('codec_name');            //返回codec_name属性 
$ffprobe = FFMpeg\FFProbe::create();
$ffprobe
    ->format('/path/to/video/mp4') //提取文件信息
    ->get('duration');              //返回duration属性

验证媒体文件

(从0.10.0开始)您可以使用PHP-FFMpeg的FFProbe包装器来验证媒体文件。

$ffprobe = FFMpeg\FFProbe::create();
$ffprobe->isValid('/path/to/file/to/check'); //返回布尔值

与Silex Microframework一起使用

服务提供商易于设置:

$app = new Silex\Application();
$app->register(new FFMpeg\FFMpegServiceProvider());

$video = $app['ffmpeg']->open('video.mpeg');

可用选项如下:

$app->register(new FFMpeg\FFMpegServiceProvider(), array(
    'ffmpeg.configuration' => array(
        'ffmpeg.threads'   => 4,
        'ffmpeg.timeout'   => 300,
        'ffmpeg.binaries'  => '/opt/local/ffmpeg/bin/ffmpeg',
        'ffprobe.timeout'  => 30,
        'ffprobe.binaries' => '/opt/local/ffmpeg/bin/ffprobe',
    ),
    'ffmpeg.logger' => $logger,
));

执照

该项目已获得 MIT license.

音乐:Waylon Thornton的“收藏夹的秘密”,来自免费音乐档案
CC BY NC SA

音乐:Jahzzar的“ Siesta”,来自免费音乐档案
CC BY SA

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42799222/article/details/105452373

智能推荐

稀疏编码的数学基础与理论分析-程序员宅基地

文章浏览阅读290次,点赞8次,收藏10次。1.背景介绍稀疏编码是一种用于处理稀疏数据的编码技术,其主要应用于信息传输、存储和处理等领域。稀疏数据是指数据中大部分元素为零或近似于零的数据,例如文本、图像、音频、视频等。稀疏编码的核心思想是将稀疏数据表示为非零元素和它们对应的位置信息,从而减少存储空间和计算复杂度。稀疏编码的研究起源于1990年代,随着大数据时代的到来,稀疏编码技术的应用范围和影响力不断扩大。目前,稀疏编码已经成为计算...

EasyGBS国标流媒体服务器GB28181国标方案安装使用文档-程序员宅基地

文章浏览阅读217次。EasyGBS - GB28181 国标方案安装使用文档下载安装包下载,正式使用需商业授权, 功能一致在线演示在线API架构图EasySIPCMSSIP 中心信令服务, 单节点, 自带一个 Redis Server, 随 EasySIPCMS 自启动, 不需要手动运行EasySIPSMSSIP 流媒体服务, 根..._easygbs-windows-2.6.0-23042316使用文档

【Web】记录巅峰极客2023 BabyURL题目复现——Jackson原生链_原生jackson 反序列化链子-程序员宅基地

文章浏览阅读1.2k次,点赞27次,收藏7次。2023巅峰极客 BabyURL之前AliyunCTF Bypassit I这题考查了这样一条链子:其实就是Jackson的原生反序列化利用今天复现的这题也是大同小异,一起来整一下。_原生jackson 反序列化链子

一文搞懂SpringCloud,详解干货,做好笔记_spring cloud-程序员宅基地

文章浏览阅读734次,点赞9次,收藏7次。微服务架构简单的说就是将单体应用进一步拆分,拆分成更小的服务,每个服务都是一个可以独立运行的项目。这么多小服务,如何管理他们?(服务治理 注册中心[服务注册 发现 剔除])这么多小服务,他们之间如何通讯?这么多小服务,客户端怎么访问他们?(网关)这么多小服务,一旦出现问题了,应该如何自处理?(容错)这么多小服务,一旦出现问题了,应该如何排错?(链路追踪)对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对每一个问题提供了相应的组件来解决它们。_spring cloud

Js实现图片点击切换与轮播-程序员宅基地

文章浏览阅读5.9k次,点赞6次,收藏20次。Js实现图片点击切换与轮播图片点击切换<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <script type="text/ja..._点击图片进行轮播图切换

tensorflow-gpu版本安装教程(过程详细)_tensorflow gpu版本安装-程序员宅基地

文章浏览阅读10w+次,点赞245次,收藏1.5k次。在开始安装前,如果你的电脑装过tensorflow,请先把他们卸载干净,包括依赖的包(tensorflow-estimator、tensorboard、tensorflow、keras-applications、keras-preprocessing),不然后续安装了tensorflow-gpu可能会出现找不到cuda的问题。cuda、cudnn。..._tensorflow gpu版本安装

随便推点

物联网时代 权限滥用漏洞的攻击及防御-程序员宅基地

文章浏览阅读243次。0x00 简介权限滥用漏洞一般归类于逻辑问题,是指服务端功能开放过多或权限限制不严格,导致攻击者可以通过直接或间接调用的方式达到攻击效果。随着物联网时代的到来,这种漏洞已经屡见不鲜,各种漏洞组合利用也是千奇百怪、五花八门,这里总结漏洞是为了更好地应对和预防,如有不妥之处还请业内人士多多指教。0x01 背景2014年4月,在比特币飞涨的时代某网站曾经..._使用物联网漏洞的使用者

Visual Odometry and Depth Calculation--Epipolar Geometry--Direct Method--PnP_normalized plane coordinates-程序员宅基地

文章浏览阅读786次。A. Epipolar geometry and triangulationThe epipolar geometry mainly adopts the feature point method, such as SIFT, SURF and ORB, etc. to obtain the feature points corresponding to two frames of images. As shown in Figure 1, let the first image be ​ and th_normalized plane coordinates

开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先抽取关系)_语义角色增强的关系抽取-程序员宅基地

文章浏览阅读708次,点赞2次,收藏3次。开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先关系再实体)一.第二代开放信息抽取系统背景​ 第一代开放信息抽取系统(Open Information Extraction, OIE, learning-based, 自学习, 先抽取实体)通常抽取大量冗余信息,为了消除这些冗余信息,诞生了第二代开放信息抽取系统。二.第二代开放信息抽取系统历史第二代开放信息抽取系统着眼于解决第一代系统的三大问题: 大量非信息性提取(即省略关键信息的提取)、_语义角色增强的关系抽取

10个顶尖响应式HTML5网页_html欢迎页面-程序员宅基地

文章浏览阅读1.1w次,点赞6次,收藏51次。快速完成网页设计,10个顶尖响应式HTML5网页模板助你一臂之力为了寻找一个优质的网页模板,网页设计师和开发者往往可能会花上大半天的时间。不过幸运的是,现在的网页设计师和开发人员已经开始共享HTML5,Bootstrap和CSS3中的免费网页模板资源。鉴于网站模板的灵活性和强大的功能,现在广大设计师和开发者对html5网站的实际需求日益增长。为了造福大众,Mockplus的小伙伴整理了2018年最..._html欢迎页面

计算机二级 考试科目,2018全国计算机等级考试调整,一、二级都增加了考试科目...-程序员宅基地

文章浏览阅读282次。原标题:2018全国计算机等级考试调整,一、二级都增加了考试科目全国计算机等级考试将于9月15-17日举行。在备考的最后冲刺阶段,小编为大家整理了今年新公布的全国计算机等级考试调整方案,希望对备考的小伙伴有所帮助,快随小编往下看吧!从2018年3月开始,全国计算机等级考试实施2018版考试大纲,并按新体系开考各个考试级别。具体调整内容如下:一、考试级别及科目1.一级新增“网络安全素质教育”科目(代..._计算机二级增报科目什么意思

conan简单使用_apt install conan-程序员宅基地

文章浏览阅读240次。conan简单使用。_apt install conan