草庐IT

C++调用Qt项目简易开发环境搭建(以视频播放器为例,附整个工程源码,支持win32_x64_debug_release,只需安装vs即可下载工程进行编译)

程序员阿周 2023-06-23 原文

一、本文主要内容介绍:
0、先附上工程源码下载链接(资源包括qt的vs2019所有库文件,免积分):https://download.csdn.net/download/qq_39660930/85135035
1、从零开始搭建一份Qt项目开发工程,只需安装了vs即可打开工程进行编译。原理:使用C++调用Qt lib库的形式进行开发,不使用任何插件,不使用QtCreator。
2、vs配置项目教程。
3、注意点:对于C++开发者来讲,就是写cpp代码,然后进行编译,链接来生成可执行程序。而Qt只是提供了一些自动生成cpp代码的功能而已。比如使用Qt的uic.exe即可将它的.ui文件生成我们的.h文件。
4、Qt开发一个简易视频播放器,支持拖拽文件进行打开、双击全屏等功能。软件界面如下:

二、项目开始
1、下载vs,本文使用的是 vs2019。
2、下载vs对应的Qt lib库,包括Qt的一些应用程序(本文附带的工程源码里有,包括win32和x64的debug及release),如图:

3、项目框架搭建

BaseFunc模块提供一些编码转换函数及获取可执行程序绝对路径函数。
GuiMediaPlayer模块进行界面设计及功能实现。
MediaPlayer主函数模块负责链接库生成可执行程序。
vs2019工程配置文件夹则是vs配置工程时自动生成的,接下来详细介绍如何配置项目工程。
4、打开vs,创建新项目,选择空白解决方案:



5、创建BaseFunc工程






将BaseFunc的头文件及源文件添加到工程里:

设置工程属性(输出目录、中间目录、配置类型、字符集、附加包含目录、预处理器):








生成项目即可看到对应的lib库:

至此BaseFunc项目配置完成。
6、创建GuiMediaPlayer工程



拖拽头文件、源文件、资源文件到工程里:

这里需要注意的是:qrc和ui文件创建时只需要按照qt语法写一个最简单的就行,后面使用qt对应的程序来进行设计即可。
接下来设置工程属性(输出目录、中间目录、配置类型、字符集、附加包含目录、预处理器):



预处理器:和BaseFunc项目一样。
Qt项目和普通的项目配置不同的地方就是要配置生成前事件,来使用Qt的exe来处理资源文件生成c++源码文件,配置如下:

命令行代码:

$(SolutionDir)..\openbsd\qt\lib\$(Platform)\Release\uic.exe $(SolutionDir)..\modules\$(ProjectName)\src\GuiMediaPlayer.ui -o $(SolutionDir)..\modules\$(ProjectName)\inc\ui_GuiMediaPlayer.h
$(SolutionDir)..\openbsd\qt\lib\$(Platform)\Release\moc.exe $(SolutionDir)..\modules\$(ProjectName)\inc\GuiMediaPlayer.h -o $(SolutionDir)..\modules\$(ProjectName)\src\moc_GuiMediaPlayer.cpp
$(SolutionDir)..\openbsd\qt\lib\$(platform)\Release\rcc.exe -binary $(SolutionDir)..\modules\$(ProjectName)\src\GuiMediaPlayer.qrc -o $(SolutionDir)..\modules\$(ProjectName)\src\GuiMediaPlayer.rcc

然后生成项目:

第一次生成项目后,需要把自动生成的源码文件添加到工程里,然后重新生成:

接下来配置如何编辑qrc和ui文件,右击qrc文件,选择打开方式,点击添加,选择QrcEditor.exe(Qt库文件里有),并且设置为默认值:


这样以后双击qrc文件就会自动使用QrcEditor来打开了:

同样右击ui文件,设置designer.exe来默认打开该文件:


这样就可以使用Qt Designer来设计我们的ui了,每次修改ui文件后,重新生成该项目即可。
至此GuiMediaPlayer项目配置完成。
7、创建主项目工程
右击解决方案,添加项目



将源文件替换为我们的main.cpp

右击该项目设为启动项目,并且设置依赖项目:


接下来设置工程属性(输出目录、中间目录、字符集、附加包含目录、预处理器、附加库目录)



预处理器:和BaseFunc项目相同。

接下来需要设置生成后事件,程序运行时需要拷贝一些资源文件及dll到对应目录:

命令行代码如下:

Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Core.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Gui.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Widgets.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Multimedia.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5MultimediaWidgets.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Network.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5OpenGL.dll"  "$(TargetDir)"
mkdir "$(TargetDir)platforms\"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\plugins\platforms\qwindows.dll"  "$(TargetDir)platforms\"
XCopy /D /i /e "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\plugins\mediaservice"  "$(TargetDir)mediaservice"

Copy /D "$(Solutiondir)..\modules\GuiMediaPlayer\src\GuiMediaPlayer.rcc"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\modules\GuiMediaPlayer\src\GuiMediaPlayer.rcc"  "$(ProjectDir)"
XCopy /D /i /e "$(Solutiondir)..\modules\GuiMediaPlayer\src\ico"  "$(TargetDir)ico"
XCopy /D /i /e "$(Solutiondir)..\modules\GuiMediaPlayer\src\ico"  "$(ProjectDir)ico"


命令行代码如下:

Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Cored.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Guid.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Widgetsd.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Multimediad.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5MultimediaWidgetsd.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5Networkd.dll"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\Qt5OpenGLd.dll"  "$(TargetDir)"
mkdir "$(TargetDir)platforms\"
Copy /D "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\plugins\platforms\qwindowsd.dll"  "$(TargetDir)platforms\"
XCopy /D /i /e "$(Solutiondir)..\openbsd\qt\lib\$(Platform)\$(Configuration)\plugins\mediaservice"  "$(TargetDir)mediaservice"

Copy /D "$(Solutiondir)..\modules\GuiMediaPlayer\src\GuiMediaPlayer.rcc"  "$(TargetDir)"
Copy /D "$(Solutiondir)..\modules\GuiMediaPlayer\src\GuiMediaPlayer.rcc"  "$(ProjectDir)"
XCopy /D /i /e "$(Solutiondir)..\modules\GuiMediaPlayer\src\ico"  "$(TargetDir)ico"
XCopy /D /i /e "$(Solutiondir)..\modules\GuiMediaPlayer\src\ico"  "$(ProjectDir)ico"

然后生成该项目后运行即可看到界面:

可以看到程序没有图标,接下来进行设置:
在MediaPlayer主工程目录下放一个ico,并且创建rc文件及修改MediaPlayer.vcxproj如下:

生成并启动项目后可以看到图标:

至此项目开发环境搭建完成。
8、ui界面设计,及功能实现
开发环境搭建好以后,我们就可以双击ui文件来进行设计界面了,我们的这个界面比较简单,菜单里增加一个文件打开按钮,并且设置该按钮的ico图标为qrc里的。中央布局背景通过styleSheet来直接使用ico路径,这样我们可以在程序发布后灵活替换背景图片。

9、播放功能实现,代码比较简单,请直接看代码:
GuiMediaPlayer.h:

#pragma once

#include <QtCore/qthread.h>
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/QVariant>

#include <QtGui/QMouseEvent>
#include <QtGui/QImage>

#include <QtWidgets/qmessagebox.h>
#include <QtWidgets/QPushButton>
#include <QtWidgets/qfiledialog.h>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>
#include <QtWidgets/QLabel>
#include <QtWidgets/QtWidgets>
#include <QtWidgets/qfiledialog.h>

#include <QtMultimedia/qmediaplayer.h>
#include <QtMultimedia/qmediaplaylist.h>
#include <QtMultimediaWidgets/QVideoWidget>

#include "ui_GuiMediaPlayer.h"

typedef enum enThreadState
{
	THREAD_STATE_E_Start = 0,
	THREAD_STATE_E_PrepareStop,
	THREAD_STATE_E_Stop
}THREAD_STATE_E;

class GuiMediaPlayer;
class GuiMediaPlayerThread :public QThread
{
	Q_OBJECT
public:
	GuiMediaPlayerThread(QObject* parent, GuiMediaPlayer* gui);
	~GuiMediaPlayerThread();

	void run();//线程入口函数(工作线程的主函数)

private:
	GuiMediaPlayer* m_gui;
};

class GuiMediaPlayer : public QMainWindow
{
	Q_OBJECT

public:
    static GuiMediaPlayer* instance();
    
	GuiMediaPlayer(QWidget* parent = Q_NULLPTR);
	~GuiMediaPlayer();

	THREAD_STATE_E	getThreadState() { return m_thread_state; };
	int				setThreadState(THREAD_STATE_E state) { return m_thread_state = state; };
	void			startThread();
	void			stopThread();

protected:
	//拖动进入事件
	void dragEnterEvent(QDragEnterEvent* event);

	//放下事件
	void dropEvent(QDropEvent* event);

	//关闭按钮触发
	void closeEvent(QCloseEvent* event);

	//鼠标按下
	void mousePressEvent(QMouseEvent* e);

	//鼠标移动
	void mouseMoveEvent(QMouseEvent* e);

	//鼠标释放
	void mouseReleaseEvent(QMouseEvent* e);

	//鼠标进入
	void enterEvent(QEvent* e);

	//鼠标离开
	void leaveEvent(QEvent* e);

	//窗口缩放
	void resizeEvent(QResizeEvent* event);

	//键盘按下
	void keyPressEvent(QKeyEvent* event);

	//事件捕获
	bool eventFilter(QObject* obj, QEvent* event);

private:
	void playFile(QString filename);

signals:
	void sigUpdateState();

private slots:
	void on_m_openFile_button_triggered();
	void updateState();

private:
	Ui::GuiMediaPlayerClass ui;
	THREAD_STATE_E			m_thread_state;
	GuiMediaPlayerThread*	m_thread;
	QMediaPlayer*			m_player;
	QVideoWidget*			m_playerWidget;
	int						m_twopress;
};

GuiMediaPlayer.cpp:

#include <string.h>
#include <atlconv.h>

#include "GuiMediaPlayer.h"

#include "BaseFunc.h"

GuiMediaPlayerThread::GuiMediaPlayerThread(QObject* parent, GuiMediaPlayer* gui)
	:QThread(parent)
{
	m_gui = NULL;

	if (gui == NULL)
		return;

	m_gui = gui;

	start();
}

GuiMediaPlayerThread::~GuiMediaPlayerThread()
{
}

void GuiMediaPlayerThread::run()
{
	while (1)
	{
		//程序退出时终止线程
		if (m_gui->getThreadState() == THREAD_STATE_E_PrepareStop)
		{
			m_gui->setThreadState(THREAD_STATE_E_Stop);
			return;
		}

		emit m_gui->sigUpdateState();

		QThread::msleep(1000);
	}
}

GuiMediaPlayer* GuiMediaPlayer::instance()
{
	static GuiMediaPlayer* _ins = NULL;
	if ( _ins == NULL )
	{
		_ins = new GuiMediaPlayer();
	}

	return _ins;
}

GuiMediaPlayer::GuiMediaPlayer(QWidget* parent)
	: QMainWindow(parent)
{
    char path[1024] = {0};
    char processname[1024] = {0};
    GetExecutablePath(path, processname, sizeof(path));

    QString rcc = path;
	rcc += "GuiMediaPlayer.rcc";

	QResource::registerResource(rcc);

	ui.setupUi(this);
    
    //启用控件的放下操作
	setAcceptDrops(true);

	m_player = NULL;
	m_playerWidget = NULL;

	m_twopress = 0;

	m_thread = NULL;

	connect(this, SIGNAL(sigUpdateState()), this, SLOT(updateState()));

	startThread();
}

GuiMediaPlayer::~GuiMediaPlayer()
{
	stopThread();
	if (m_player != NULL)
	{
		delete m_player;
		m_player = NULL;
	}
	if (m_playerWidget != NULL)
	{
		delete m_playerWidget;
		m_playerWidget = NULL;
	}
}

void GuiMediaPlayer::startThread()
{
	m_thread_state = THREAD_STATE_E_Start;
	m_thread = new GuiMediaPlayerThread(NULL, this);
}

void GuiMediaPlayer::stopThread()
{
	if (m_thread)
	{
		//设置准备停止状态
		m_thread_state = THREAD_STATE_E_PrepareStop;
		//一直等到停止
		while (1)
		{
			//printf("wait show img thread stop\n");
			if (m_thread_state == THREAD_STATE_E_Stop)
				break;
			QThread::msleep(100);
		}
		QThread::msleep(50);
		delete m_thread;
		m_thread = NULL;
	}
}

void GuiMediaPlayer::updateState()
{
	if (m_player)
	{
		if (m_player->mediaStatus() == QMediaPlayer::EndOfMedia)
		{
			if (m_playerWidget != NULL)
			{
				delete m_playerWidget;
				m_playerWidget = NULL;
			}

			delete m_player;
			m_player = NULL;
		}
	}
}

void GuiMediaPlayer::playFile(QString filename)
{
	if (m_playerWidget != NULL)
	{
		delete m_playerWidget;
		m_playerWidget = NULL;
	}

	if (m_player != NULL)
	{
		delete m_player;
		m_player = NULL;
	}

	m_playerWidget = new QVideoWidget;
	if (m_playerWidget == NULL)
	{
		return;
	}
	m_playerWidget->setObjectName(QString::fromUtf8("play_widget"));
	ui.verticalLayout->addWidget(m_playerWidget);
	m_playerWidget->installEventFilter(this);

	m_player = new QMediaPlayer;
	if (m_player == NULL)
	{
		return;
	}

	m_player->setVideoOutput(m_playerWidget);
	m_player->setMedia(QUrl::fromLocalFile(filename));
	m_player->play();
}

void GuiMediaPlayer::on_m_openFile_button_triggered()
{   
	QString filename = QFileDialog::getOpenFileName();
	if (filename.toStdString() == "")
		return;

	playFile(filename);

    return ;    
}

/*拖放分为拖动(Drag)和放下(Drop)两种操作。数据拖动时会被存储为MIME(Multipurpose-
 * Internet Mail Extensions)类型,在Qt使用QMimeData类来表示MIME类型数据,并还用
 * QDrag类来完成数据的转换,而整个拖放操作都是在几个鼠标事件和拖放事件中完成.
*/
void GuiMediaPlayer::dragEnterEvent(QDragEnterEvent* event)//拖动事件
{
	//可打开.txt,.h,.cpp文件
	if (event->mimeData()->hasUrls())   //数据中是否包含URL
		event->acceptProposedAction(); //如果是则接受动作
	else 
		event->ignore();
}

void GuiMediaPlayer::dropEvent(QDropEvent* event)//放下事件
{
	const QMimeData* mineData = event->mimeData();//获取MIME数据
	if (mineData->hasUrls())                     //如数据中包含URL
	{
		QList<QUrl>urlList = mineData->urls();    //获取URL列表
		if (urlList.isEmpty())
			return;
		//将其中第一个URL表示为本地文件路径
		QString filename = urlList.at(0).toLocalFile();
		if (filename.isEmpty())
			return;

		playFile(filename);
	}
}

void GuiMediaPlayer::closeEvent(QCloseEvent* event)
{
	if (1)
	{
		stopThread();
		event->accept();
	}
	else
	{
		event->ignore();
	}
}

void GuiMediaPlayer::mousePressEvent(QMouseEvent* e)
{
	QPoint lastPoint = e->globalPos();
	//printf("%d %d\n", lastPoint.x(), lastPoint.y());
}

void GuiMediaPlayer::mouseMoveEvent(QMouseEvent* e)
{
	//printf("%d %d\n", e->globalX(), e->globalY());
}

void GuiMediaPlayer::mouseReleaseEvent(QMouseEvent* e)
{
	//printf("%d %d\n", e->globalX(), e->globalY());
}

void GuiMediaPlayer::enterEvent(QEvent* e)
{
}

void GuiMediaPlayer::leaveEvent(QEvent* e)
{
}

void GuiMediaPlayer::resizeEvent(QResizeEvent* event)
{
}

void GuiMediaPlayer::keyPressEvent(QKeyEvent* event)
{
	if (event->key() == Qt::Key_Q)
	{
	}
	else if (event->key() == Qt::Key_Left)
	{
	}
	else if (event->key() == Qt::Key_Right)
	{
	}
	else if (event->key() == Qt::Key_Up)
	{
	}
	else if (event->key() == Qt::Key_Down)
	{
	}
	else if (event->key() == Qt::Key_Backspace)
	{
	}
	else if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
	{
	}
	else
	{
	}
}

bool GuiMediaPlayer::eventFilter(QObject* obj, QEvent* event)
{
	if (event->type() == QEvent::KeyPress)
	{
		QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
		if (keyEvent->key() == Qt::Key_Backspace)
		{
		}
	}

	if (obj == m_playerWidget)
	{
		if (event->type() == QEvent::MouseButtonDblClick)
		{
			m_twopress++;
			if (m_twopress % 2)
				m_playerWidget->setFullScreen(true);
			else
				m_playerWidget->setFullScreen(false);
		}
	}

	return QWidget::eventFilter(obj, event);
}

10、其他注意项
依赖库输入直接在main.cpp里指定的:

关闭打开控制台代码也在main.cpp里:

程序运行后如果播放视频没图像,则需要安装解码器,安装包在openbsd\qt\lib\LAVFilters-0.76.1-Installer.exe。

有关C++调用Qt项目简易开发环境搭建(以视频播放器为例,附整个工程源码,支持win32_x64_debug_release,只需安装vs即可下载工程进行编译)的更多相关文章

  1. ruby-on-rails - Railstutorial : db:populate vs. 工厂女孩 - 2

    在railstutorial中,作者为什么选择使用这个(代码list10.25):http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-usersnamespace:dbdodesc"Filldatabasewithsampledata"task:populate=>:environmentdoRake::Task['db:reset'].invokeUser.create!(:name=>"ExampleUser",:email=>"example@railstutorial.org",:passwo

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  4. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  5. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

  6. Qt Designer的简单使用 - 2

    在前面两节的例子中,主界面窗口的尺寸和标签控件显示的矩形区域等,都是用C++代码编写的。窗口和控件的尺寸都是预估的,控件如果多起来,那就不好估计每个控件合适的位置和大小了。用C++代码编写图形界面的问题就是不直观,因此Qt项目开发了专门的可视化图形界面编辑器——QtDesigner(Qt设计师)。通过QtDesigner就可以很方便地创建图形界面文件*.ui,然后将ui文件应用到源代码里面,做到“所见即所得”,大大方便了图形界面的设计。本节就演示一下QtDesigner的简单使用,学习拖拽控件和设置控件属性,并将ui文件应用到Qt程序代码里。使用QtDesigner设计界面在开始菜单中找到「Q

  7. 动漫制作技巧如何制作动漫视频 - 2

    动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、

  8. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  9. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  10. ruby - 如何在 Ruby 字符串中插入项目符号字符? - 2

    我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195

随机推荐