mirror of
https://gitlab.com/kelteseth/ScreenPlay.git
synced 2024-11-06 19:12:30 +01:00
Add mp4 import
This commit is contained in:
parent
6b653bdfdc
commit
2b5b7f0aad
@ -94,5 +94,8 @@
|
||||
<file>qml/Workshop/SteamWorkshop.qml</file>
|
||||
<file>qml/Workshop/Forum.qml</file>
|
||||
<file>qml/Workshop/SteamWorkshopStartPage.qml</file>
|
||||
<file>qml/Create/Wizards/Importh264/Importh264.qml</file>
|
||||
<file>qml/Create/Wizards/Importh264/Importh264Convert.qml</file>
|
||||
<file>qml/Create/Wizards/Importh264/Importh264Init.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -25,69 +25,6 @@ Rectangle {
|
||||
color: Material.background
|
||||
|
||||
ListView {
|
||||
|
||||
|
||||
/*
|
||||
ListElement {
|
||||
headline: qsTr("QML Particle Wallpaper")
|
||||
source: ""
|
||||
category: "Example Wallpaper"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("Countdown Clock Wallpaper")
|
||||
source: ""
|
||||
category: "Example Wallpaper"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("QML Water Shader Wallpaper")
|
||||
source: ""
|
||||
category: "Example Wallpaper"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("QML Shadertoy Shader Wallpaper")
|
||||
source: ""
|
||||
category: "Example Wallpaper"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("QML Lightning Shader Wallpaper")
|
||||
source: ""
|
||||
category: "Example Wallpaper"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("Clock Widget")
|
||||
source: "qrc:/qml/Create/Wizards/CreateEmptyWidget/CreateEmptyWidget.qml"
|
||||
category: "Example Widget"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("CPU Widget")
|
||||
source: "qrc:/qml/Create/Wizards/CreateEmptyWidget/CreateEmptyWidget.qml"
|
||||
category: "Example Widget"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("Storage Widget")
|
||||
source: "qrc:/qml/Create/Wizards/CreateEmptyWidget/CreateEmptyWidget.qml"
|
||||
category: "Example Widget"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("RAM Widget")
|
||||
source: "qrc:/qml/Create/Wizards/CreateEmptyWidget/CreateEmptyWidget.qml"
|
||||
category: "Example Widget"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("XKCD Widget")
|
||||
source: "qrc:/qml/Create/Wizards/CreateEmptyWidget/CreateEmptyWidget.qml"
|
||||
category: "Example Widget"
|
||||
}
|
||||
*/
|
||||
id: listView
|
||||
objectName: "wizardsListView"
|
||||
|
||||
@ -130,7 +67,14 @@ Rectangle {
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("Video Import (.webm)")
|
||||
headline: qsTr("Video Import h264 (.mp4)")
|
||||
source: "qrc:/qml/Create/Wizards/Importh264/Importh264.qml"
|
||||
category: "Video Wallpaper"
|
||||
objectName: ""
|
||||
}
|
||||
|
||||
ListElement {
|
||||
headline: qsTr("Video Import VP8 & VP9 (.webm)")
|
||||
source: "qrc:/qml/Create/Wizards/ImportWebm/ImportWebm.qml"
|
||||
category: "Video Wallpaper"
|
||||
objectName: ""
|
||||
|
@ -16,7 +16,7 @@ Item {
|
||||
Common.Headline {
|
||||
id: headline
|
||||
|
||||
text: qsTr("Free Tools to create wallpaper")
|
||||
text: qsTr("Free tools to help you to create wallpaper")
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
@ -33,7 +33,7 @@ Item {
|
||||
color: Material.primaryTextColor
|
||||
font.pointSize: 12
|
||||
font.family: ScreenPlay.settings.font
|
||||
text: qsTr("Below you can find tools to create wallaper beyond the tools that ScreenPlay provides for you!")
|
||||
text: qsTr("Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you!")
|
||||
|
||||
anchors {
|
||||
top: headline.bottom
|
||||
|
@ -202,7 +202,6 @@ Item {
|
||||
id: txtConvertNumber
|
||||
|
||||
color: "white"
|
||||
text: qsTr("")
|
||||
font.pointSize: 21
|
||||
font.family: ScreenPlay.settings.font
|
||||
|
||||
|
@ -197,7 +197,6 @@ Item {
|
||||
id: txtConvertNumber
|
||||
|
||||
color: "white"
|
||||
text: qsTr("")
|
||||
font.pointSize: 21
|
||||
font.family: ScreenPlay.settings.font
|
||||
|
||||
|
41
ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml
Normal file
41
ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml
Normal file
@ -0,0 +1,41 @@
|
||||
import QtQuick
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Material
|
||||
import QtQuick.Layouts
|
||||
import ScreenPlay 1.0
|
||||
import ScreenPlay.Create 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
signal wizardStarted()
|
||||
signal wizardExited()
|
||||
signal next()
|
||||
|
||||
SwipeView {
|
||||
id: swipeView
|
||||
|
||||
anchors.fill: parent
|
||||
interactive: false
|
||||
clip: true
|
||||
|
||||
Importh264Init {
|
||||
onNext: (filePath) =>{
|
||||
root.wizardStarted();
|
||||
swipeView.currentIndex = 1;
|
||||
createWallpaperVideoImportConvert.filePath = filePath;
|
||||
ScreenPlay.util.setNavigationActive(false);
|
||||
ScreenPlay.create.importH264(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
Importh264Convert {
|
||||
id: createWallpaperVideoImportConvert
|
||||
|
||||
onExit: root.wizardExited()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
396
ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml
Normal file
396
ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml
Normal file
@ -0,0 +1,396 @@
|
||||
import QtQuick
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Material
|
||||
import QtQuick.Layouts
|
||||
import ScreenPlay 1.0
|
||||
import ScreenPlay.Create 1.0
|
||||
import ScreenPlay.Enums.ImportVideoState 1.0
|
||||
import "../../../Common" as Common
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property bool conversionFinishedSuccessful: false
|
||||
property bool canSave: false
|
||||
property string filePath
|
||||
|
||||
signal exit()
|
||||
signal save()
|
||||
|
||||
function basename(str) {
|
||||
let filenameWithExtentions = (str.slice(str.lastIndexOf("/") + 1));
|
||||
let filename = filenameWithExtentions.split('.').slice(0, -1).join('.');
|
||||
return filename;
|
||||
}
|
||||
|
||||
function checkCanSave() {
|
||||
if (canSave && conversionFinishedSuccessful)
|
||||
btnSave.enabled = true;
|
||||
else
|
||||
btnSave.enabled = false;
|
||||
}
|
||||
|
||||
onCanSaveChanged: root.checkCanSave()
|
||||
onFilePathChanged: {
|
||||
textFieldName.text = basename(filePath);
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onCreateWallpaperStateChanged(state) {
|
||||
switch (state) {
|
||||
case ImportVideoState.AnalyseVideo:
|
||||
txtConvert.text = qsTr("AnalyseVideo...");
|
||||
break;
|
||||
case ImportVideoState.ConvertingPreviewImage:
|
||||
txtConvert.text = qsTr("Generating preview image...");
|
||||
break;
|
||||
case ImportVideoState.ConvertingPreviewThumbnailImage:
|
||||
txtConvert.text = qsTr("Generating preview thumbnail image...");
|
||||
break;
|
||||
case ImportVideoState.ConvertingPreviewImageFinished:
|
||||
imgPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.jpg";
|
||||
imgPreview.visible = true;
|
||||
break;
|
||||
case ImportVideoState.ConvertingPreviewVideo:
|
||||
txtConvert.text = qsTr("Generating 5 second preview video...");
|
||||
break;
|
||||
case ImportVideoState.ConvertingPreviewGif:
|
||||
txtConvert.text = qsTr("Generating preview gif...");
|
||||
break;
|
||||
case ImportVideoState.ConvertingPreviewGifFinished:
|
||||
gifPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.gif";
|
||||
imgPreview.visible = false;
|
||||
gifPreview.visible = true;
|
||||
gifPreview.playing = true;
|
||||
break;
|
||||
case ImportVideoState.ConvertingAudio:
|
||||
txtConvert.text = qsTr("Converting Audio...");
|
||||
break;
|
||||
case ImportVideoState.ConvertingVideo:
|
||||
txtConvert.text = qsTr("Converting Video... This can take some time!");
|
||||
break;
|
||||
case ImportVideoState.ConvertingVideoError:
|
||||
txtConvert.text = qsTr("Converting Video ERROR!");
|
||||
break;
|
||||
case ImportVideoState.AnalyseVideoError:
|
||||
txtConvert.text = qsTr("Analyse Video ERROR!");
|
||||
break;
|
||||
case ImportVideoState.Finished:
|
||||
txtConvert.text = "";
|
||||
conversionFinishedSuccessful = true;
|
||||
busyIndicator.running = false;
|
||||
btnExit.enabled = false;
|
||||
root.checkCanSave();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function onProgressChanged(progress) {
|
||||
var percentage = Math.floor(progress * 100);
|
||||
if (percentage > 100 || progress > 0.95)
|
||||
percentage = 100;
|
||||
|
||||
if (percentage === NaN)
|
||||
print(progress, percentage);
|
||||
|
||||
txtConvertNumber.text = percentage + "%";
|
||||
}
|
||||
|
||||
target: ScreenPlay.create
|
||||
}
|
||||
|
||||
Common.Headline {
|
||||
id: txtHeadline
|
||||
|
||||
text: qsTr("Import a video to a wallpaper")
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
margins: 40
|
||||
bottomMargin: 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
id: wrapperLeft
|
||||
|
||||
width: parent.width * 0.66
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: txtHeadline.bottom
|
||||
margins: 30
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: imgWrapper
|
||||
|
||||
color: Material.color(Material.Grey)
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
rightMargin: 20
|
||||
bottom: previewSelector.top
|
||||
bottomMargin: 20
|
||||
left: parent.left
|
||||
}
|
||||
|
||||
Image {
|
||||
id: imgPreview
|
||||
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
asynchronous: true
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
AnimatedImage {
|
||||
id: gifPreview
|
||||
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
asynchronous: true
|
||||
playing: true
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
LinearGradient {
|
||||
id: shadow
|
||||
|
||||
cached: true
|
||||
anchors.fill: parent
|
||||
start: Qt.point(0, height)
|
||||
end: Qt.point(0, 0)
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
id: gradientStop0
|
||||
|
||||
position: 0
|
||||
color: "#DD000000"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
id: gradientStop1
|
||||
|
||||
position: 1
|
||||
color: "#00000000"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: busyIndicator
|
||||
|
||||
anchors.centerIn: parent
|
||||
running: true
|
||||
}
|
||||
|
||||
Text {
|
||||
id: txtConvertNumber
|
||||
|
||||
color: "white"
|
||||
font.pointSize: 21
|
||||
font.family: ScreenPlay.settings.font
|
||||
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: 40
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Text {
|
||||
id: txtConvert
|
||||
|
||||
color: Material.secondaryTextColor
|
||||
text: qsTr("Generating preview video...")
|
||||
font.pointSize: 14
|
||||
font.family: ScreenPlay.settings.font
|
||||
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: 20
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Common.ImageSelector {
|
||||
id: previewSelector
|
||||
|
||||
height: 80
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: 20
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
id: wrapperRight
|
||||
|
||||
width: parent.width * 0.33
|
||||
|
||||
anchors {
|
||||
top: txtHeadline.bottom
|
||||
topMargin: 30
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
|
||||
spacing: 0
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
left: parent.left
|
||||
margins: 30
|
||||
top: parent.top
|
||||
topMargin: 0
|
||||
bottom: column1.top
|
||||
bottomMargin: 50
|
||||
}
|
||||
|
||||
Common.TextField {
|
||||
id: textFieldName
|
||||
|
||||
placeholderText: qsTr("Name (required!)")
|
||||
width: parent.width
|
||||
Layout.fillWidth: true
|
||||
onTextChanged: {
|
||||
if (textFieldName.text.length >= 3)
|
||||
canSave = true;
|
||||
else
|
||||
canSave = false;
|
||||
}
|
||||
}
|
||||
|
||||
Common.TextField {
|
||||
id: textFieldDescription
|
||||
|
||||
placeholderText: qsTr("Description")
|
||||
width: parent.width
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Common.TextField {
|
||||
id: textFieldYoutubeURL
|
||||
|
||||
placeholderText: qsTr("Youtube URL")
|
||||
width: parent.width
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Common.TagSelector {
|
||||
id: textFieldTags
|
||||
|
||||
width: parent.width
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Row {
|
||||
id: column1
|
||||
|
||||
height: 80
|
||||
width: childrenRect.width
|
||||
spacing: 10
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: 30
|
||||
bottomMargin: -10
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
Button {
|
||||
id: btnExit
|
||||
|
||||
text: qsTr("Abort")
|
||||
Material.background: Material.Red
|
||||
Material.foreground: "white"
|
||||
font.family: ScreenPlay.settings.font
|
||||
onClicked: {
|
||||
root.exit();
|
||||
ScreenPlay.create.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: btnSave
|
||||
objectName: "btnSave"
|
||||
text: qsTr("Save")
|
||||
enabled: false
|
||||
Material.background: Material.accent
|
||||
Material.foreground: "white"
|
||||
font.family: ScreenPlay.settings.font
|
||||
onClicked: {
|
||||
if (conversionFinishedSuccessful) {
|
||||
btnSave.enabled = false;
|
||||
ScreenPlay.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, Create.H264, textFieldTags.getTags());
|
||||
savePopup.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Popup {
|
||||
id: savePopup
|
||||
|
||||
modal: true
|
||||
focus: true
|
||||
width: 250
|
||||
anchors.centerIn: parent
|
||||
height: 200
|
||||
onOpened: timerSave.start()
|
||||
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
running: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Save Wallpaper...")
|
||||
color: Material.primaryTextColor
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 30
|
||||
font.family: ScreenPlay.settings.font
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timerSave
|
||||
|
||||
interval: 1000 + Math.random() * 1000
|
||||
onTriggered: {
|
||||
savePopup.close();
|
||||
ScreenPlay.util.setNavigationActive(true);
|
||||
root.exit();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
162
ScreenPlay/qml/Create/Wizards/Importh264/Importh264Init.qml
Normal file
162
ScreenPlay/qml/Create/Wizards/Importh264/Importh264Init.qml
Normal file
@ -0,0 +1,162 @@
|
||||
import QtQuick
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Material
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Dialogs
|
||||
import ScreenPlay 1.0
|
||||
import ScreenPlay.Create 1.0
|
||||
import "../../../Common" as Common
|
||||
import "../../"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
signal next(var filePath)
|
||||
|
||||
ColumnLayout {
|
||||
id: wrapper
|
||||
|
||||
spacing: 40
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: btnOpenDocs.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
margins: 20
|
||||
}
|
||||
|
||||
Common.Headline {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Import a .mp4 video")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
spacing: 40
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
spacing: 40
|
||||
|
||||
Text {
|
||||
id: txtDescription
|
||||
|
||||
text: qsTr("ScreenPlay V0.15 and up can play *.mp4 (also more known as h264). This can improove performance on older systems.")
|
||||
color: Material.primaryTextColor
|
||||
Layout.fillWidth: true
|
||||
font.pointSize: 13
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
font.family: ScreenPlay.settings.font
|
||||
}
|
||||
|
||||
DropArea {
|
||||
id: dropArea
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
onExited: {
|
||||
bg.color = Qt.darker(Material.backgroundColor)
|
||||
}
|
||||
onEntered: {
|
||||
bg.color = Qt.darker(Qt.darker(
|
||||
Material.backgroundColor))
|
||||
drag.accept(Qt.LinkAction)
|
||||
}
|
||||
onDropped: {
|
||||
let file = ScreenPlay.util.toLocal(drop.urls[0])
|
||||
bg.color = Qt.darker(Qt.darker(
|
||||
Material.backgroundColor))
|
||||
if (file.endsWith(".mp4"))
|
||||
root.next(drop.urls[0])
|
||||
else
|
||||
txtFile.text = qsTr(
|
||||
"Invalid file type. Must be valid h264 (*.mp4)!")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: bg
|
||||
|
||||
anchors.fill: parent
|
||||
radius: 3
|
||||
color: Qt.darker(Material.backgroundColor)
|
||||
}
|
||||
|
||||
Image {
|
||||
id: bgPattern
|
||||
|
||||
anchors.fill: parent
|
||||
fillMode: Image.Tile
|
||||
opacity: 0.2
|
||||
source: "qrc:/assets/images/noisy-texture-3.png"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: txtFile
|
||||
|
||||
text: qsTr("Drop a *.mp4 file here or use 'Select file' below.")
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
color: Material.primaryTextColor
|
||||
font.pointSize: 13
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
font.family: ScreenPlay.settings.font
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: 40
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: btnOpenDocs
|
||||
|
||||
text: qsTr("Open Documentation")
|
||||
Material.background: Material.LightGreen
|
||||
Material.foreground: "white"
|
||||
icon.source: "qrc:/assets/icons/icon_document.svg"
|
||||
icon.color: "white"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
font.family: ScreenPlay.settings.font
|
||||
onClicked: Qt.openUrlExternally(
|
||||
"https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance")
|
||||
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
margins: 20
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Select file")
|
||||
highlighted: true
|
||||
font.family: ScreenPlay.settings.font
|
||||
onClicked: {
|
||||
fileDialogImportVideo.open()
|
||||
}
|
||||
|
||||
FileDialog {
|
||||
id: fileDialogImportVideo
|
||||
|
||||
nameFilters: ["Video files (*.mp4)"]
|
||||
onAccepted: {
|
||||
root.next(fileDialogImportVideo.currentFile)
|
||||
}
|
||||
}
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
margins: 20
|
||||
}
|
||||
}
|
||||
}
|
@ -169,6 +169,91 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c
|
||||
m_createImportFutureWatcher.setFuture(m_createImportFuture);
|
||||
}
|
||||
|
||||
void Create::importH264(QString videoPath)
|
||||
{
|
||||
reset();
|
||||
videoPath = ScreenPlayUtil::toLocal(videoPath);
|
||||
|
||||
const QDir installedDir = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString());
|
||||
|
||||
// Create a temp dir so we can later alter it to the workshop id
|
||||
const QDateTime date = QDateTime::currentDateTime();
|
||||
const auto folderName = date.toString("ddMMyyyyhhmmss");
|
||||
setWorkingDir(installedDir.path() + "/" + folderName);
|
||||
|
||||
if (!installedDir.mkdir(folderName)) {
|
||||
qInfo() << "Unable to create folder with name: " << folderName << " at: " << installedDir;
|
||||
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateTmpFolderError);
|
||||
emit abortCreateWallpaper();
|
||||
return;
|
||||
}
|
||||
|
||||
m_createImportFuture = QtConcurrent::run(QThreadPool::globalInstance(), [videoPath, this]() {
|
||||
CreateImportVideo import(videoPath, workingDir(), m_interrupt);
|
||||
QObject::connect(&import, &CreateImportVideo::createWallpaperStateChanged, this, &Create::createWallpaperStateChanged, Qt::ConnectionType::QueuedConnection);
|
||||
QObject::connect(&import, &CreateImportVideo::abortAndCleanup, this, &Create::abortAndCleanup, Qt::ConnectionType::QueuedConnection);
|
||||
QObject::connect(
|
||||
&import, &CreateImportVideo::processOutput, this, [this](const QString text) {
|
||||
appendFfmpegOutput(text + "\n");
|
||||
},
|
||||
Qt::ConnectionType::QueuedConnection);
|
||||
|
||||
if (!import.createWallpaperInfo() || m_interrupt) {
|
||||
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
|
||||
emit import.abortAndCleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
qInfo() << "createWallpaperImageThumbnailPreview()";
|
||||
if (!import.createWallpaperImageThumbnailPreview() || m_interrupt) {
|
||||
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
|
||||
emit import.abortAndCleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
qInfo() << "createWallpaperImagePreview()";
|
||||
if (!import.createWallpaperImagePreview() || m_interrupt) {
|
||||
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
|
||||
emit import.abortAndCleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip preview convert for webm
|
||||
if (!import.createWallpaperVideoPreview() || m_interrupt) {
|
||||
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
|
||||
emit import.abortAndCleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
qInfo() << "createWallpaperGifPreview()";
|
||||
if (!import.createWallpaperGifPreview() || m_interrupt) {
|
||||
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
|
||||
emit import.abortAndCleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
// If the video has no audio we can skip the extraction
|
||||
if (!import.m_skipAudio) {
|
||||
qInfo() << "extractWallpaperAudio()";
|
||||
if (!import.extractWallpaperAudio() || m_interrupt) {
|
||||
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
|
||||
emit import.abortAndCleanup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Finished);
|
||||
return;
|
||||
});
|
||||
|
||||
QObject::connect(&m_createImportFutureWatcher, &QFutureWatcherBase::finished, this, [this]() {
|
||||
if (m_interrupt)
|
||||
abortAndCleanup();
|
||||
});
|
||||
|
||||
m_createImportFutureWatcher.setFuture(m_createImportFuture);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief When converting of the wallpaper steps where successful.
|
||||
*/
|
||||
@ -207,7 +292,7 @@ void Create::saveWallpaper(
|
||||
}
|
||||
|
||||
QFileInfo filePathFile(filePath);
|
||||
if (filePath.endsWith(".webm")) {
|
||||
if (filePath.endsWith(".webm") || filePath.endsWith(".mp4")) {
|
||||
if (!QFile::copy(filePath, m_workingDir + "/" + filePathFile.fileName())) {
|
||||
qDebug() << "Could not copy" << filePath << " to " << m_workingDir + "/" + filePathFile.fileName();
|
||||
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFilesError);
|
||||
@ -221,8 +306,8 @@ void Create::saveWallpaper(
|
||||
obj.insert("description", description);
|
||||
obj.insert("title", title);
|
||||
obj.insert("youtube", youtube);
|
||||
obj.insert("videoCodec", codec == Create::VideoCodec::VP8 ? "vp8" : "vp9");
|
||||
obj.insert("file", filePathFile.completeBaseName() + ".webm");
|
||||
obj.insert("videoCodec", QVariant::fromValue<VideoCodec>(codec).toString());
|
||||
obj.insert("file", filePathFile.completeBaseName() + (codec == VideoCodec::H264 ? ".mp4" : ".webm"));
|
||||
obj.insert("previewGIF", "preview.gif");
|
||||
obj.insert("previewWEBM", "preview.webm");
|
||||
obj.insert("preview", previewImageFile.exists() ? previewImageFile.fileName() : "preview.jpg");
|
||||
|
@ -78,7 +78,8 @@ public:
|
||||
enum class VideoCodec {
|
||||
VP8,
|
||||
VP9,
|
||||
AV1
|
||||
AV1,
|
||||
H264
|
||||
};
|
||||
Q_ENUM(VideoCodec)
|
||||
|
||||
@ -101,6 +102,8 @@ public slots:
|
||||
|
||||
void createWallpaperStart(QString videoPath, Create::VideoCodec codec = Create::VideoCodec::VP9, const int quality = 50);
|
||||
|
||||
void importH264(QString videoPath);
|
||||
|
||||
void saveWallpaper(const QString title,
|
||||
const QString description,
|
||||
QString filePath,
|
||||
|
@ -38,6 +38,21 @@ CreateImportVideo::CreateImportVideo(
|
||||
m_videoPath = videoPath;
|
||||
m_exportPath = exportPath;
|
||||
m_codec = codec;
|
||||
setupFFMPEG();
|
||||
}
|
||||
|
||||
CreateImportVideo::CreateImportVideo(const QString& videoPath, const QString& exportPath, std::atomic<bool>& interrupt)
|
||||
: QObject(nullptr)
|
||||
, m_quality(0)
|
||||
, m_interrupt(interrupt)
|
||||
{
|
||||
m_videoPath = videoPath;
|
||||
m_exportPath = exportPath;
|
||||
setupFFMPEG();
|
||||
}
|
||||
|
||||
void CreateImportVideo::setupFFMPEG()
|
||||
{
|
||||
m_ffprobeExecutable = QApplication::applicationDirPath() + "/ffprobe" + ScreenPlayUtil::executableBinEnding();
|
||||
m_ffmpegExecutable = QApplication::applicationDirPath() + "/ffmpeg" + ScreenPlayUtil::executableBinEnding();
|
||||
|
||||
|
@ -60,6 +60,7 @@ class CreateImportVideo : public QObject {
|
||||
|
||||
public:
|
||||
explicit CreateImportVideo(const QString& videoPath, const QString& exportPath, const QString& codec, const int quality, std::atomic<bool>& interrupt);
|
||||
explicit CreateImportVideo(const QString& videoPath, const QString& exportPath, std::atomic<bool>& interrupt);
|
||||
|
||||
float progress() const { return m_progress; }
|
||||
|
||||
@ -124,7 +125,9 @@ private:
|
||||
|
||||
bool analyzeWebmReadFrames(const QJsonObject& obj);
|
||||
bool analyzeVideo(const QJsonObject& obj);
|
||||
void setupFFMPEG();
|
||||
|
||||
private:
|
||||
QString m_ffprobeExecutable;
|
||||
QString m_ffmpegExecutable;
|
||||
std::unique_ptr<QProcess> m_process;
|
||||
|
Loading…
Reference in New Issue
Block a user