#include "evideo.h" #include "tools.h" #include "main.h" #include "base/ffutil.h" #include #include #include #include #include #include #include EVideo *EVideo::create(const QString &file, PageListItem *pageItem, EBase *multiWin) { int64_t dur; AVCodecID codecId; QImage img; auto err = videoInfo(file.toUtf8(), img, &dur, &codecId); if(! err.isEmpty()) { QMessageBox::critical(pageItem->listWidget(), "Video Error", err+"\n"+file); return 0; } QFileInfo rawInfo(file); auto rawName = rawInfo.fileName(); auto outFile = transcoding(pageItem->listWidget(), file, rawName, pageItem->mPageDir, img.width(), img.height(), codecId); if(outFile.isEmpty()) return 0; QFileInfo outInfo(outFile); if(! outInfo.isFile() || outInfo.size()==0) return 0; auto ins = new EVideo(outInfo.absolutePath(), outInfo.fileName(), rawInfo.absolutePath(), rawName, img, pageItem, multiWin); ins->mDuration = round(dur*0.000001); return ins; } EVideo *EVideo::create(const JObj &ele, PageListItem *pageItem, EBase *multiWin) { auto widget = ele["widget"]; if(widget.isNull()) widget = ele; auto dir = widget["path"].toString(); auto name = widget["file"].toString(); if(! QFileInfo::exists(dir)) dir = pageItem->mPageDir; auto file = dir + "/" + name; if(QFileInfo::exists(file)) ; else if(QFileInfo::exists(file = pageItem->mPageDir + "/" + name)) dir = pageItem->mPageDir; else return 0; int64_t dur; QImage img; auto err = videoInfo(file.toUtf8(), img, &dur, 0); if(! err.isEmpty()) return 0; dur = round(dur*0.000001); auto ins = new EVideo(dir, name, widget["pathRaw"].toString(), widget["fileRaw"].toString(), img, pageItem, multiWin); ins->setBaseAttr(ele); if(ins->mDuration < 4) ins->mDuration = dur; auto play = ele["play"]; ins->playTimes = (play.isNull() ? ele : play)["playTimes"].toInt(1); return ins; } EVideo::EVideo(const QString &dir, const QString &name, const QString &rawDir, const QString &rawName, QImage &coverImg, PageListItem *pageItem, EBase *multiWin) : EBase(multiWin), mDir(dir), mName(name), mRawDir(rawDir), mRawName(rawName), mCoverImg(coverImg), mPageItem(pageItem) { mType = EBase::Video; } void EVideo::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { auto inner = innerRect(); painter->save(); painter->setRenderHints(QPainter::SmoothPixmapTransform); painter->drawImage(inner, mCoverImg); double maskW = mask().width()/2, maskH = mask().height()/2; if(maskW>inner.width() || maskH>inner.height()) { double rate = qMin(inner.width() / maskW, inner.height() / maskH); maskW *= rate; maskH *= rate; } painter->drawImage(QRectF(inner.left()+(inner.width() - maskW)/2, inner.top()+(inner.height() - maskH)/2, maskW, maskH), mask()); painter->restore(); EBase::paint(painter, option, widget); } QWidget* EVideo::attrWgt() { auto wgtAttr = new QWidget; auto vBox = new QVBoxLayout(wgtAttr); vBox->setContentsMargins(6, 0, 6, 0); if(mMultiWin) vBox->setSpacing(3); addBaseAttrWgt(vBox); auto hBox = new QHBoxLayout(); hBox->addWidget(new QLabel(tr("Basic Properties"))); auto line = new QFrame(); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); hBox->addWidget(line, 1); vBox->addLayout(hBox); hBox = new QHBoxLayout(); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("File"))); auto fdFileName = new QLineEdit(mRawName); fdFileName->setReadOnly(true); hBox->addWidget(fdFileName); auto bnSelectFile = new QPushButton("..."); bnSelectFile->setFixedWidth(30); bnSelectFile->setObjectName("bnSelectFile"); connect(bnSelectFile, &QPushButton::clicked, this, [=] { auto rawFile = QFileDialog::getOpenFileName(wgtAttr, tr("Select File"), gFileHome, EVideo::filters()); if(rawFile.isEmpty()) return; QFileInfo rawInfo(rawFile); int64_t dur; AVCodecID codecId; auto err = videoInfo(rawFile.toUtf8(), mCoverImg, &dur, &codecId); if(! err.isEmpty()) { QMessageBox::critical(wgtAttr, "Video Error", err+"\n"+rawFile); return; }; mRawDir = rawInfo.absolutePath(); mRawName = rawInfo.fileName(); gFileHome = mRawDir; fdFileName->setText(mRawName); mDuration = round(dur*0.000001); fdDuration->setValue(mDuration); auto outFile = transcoding(wgtAttr, rawFile, mRawName, mPageItem->mPageDir, mCoverImg.width(), mCoverImg.height(), codecId); if(outFile.isEmpty()) return; QFileInfo outInfo(outFile); mDir = outInfo.absolutePath(); mName = outInfo.fileName(); }); hBox->addWidget(bnSelectFile); vBox->addLayout(hBox); // hBox = new QHBoxLayout(); // hBox->addSpacing(6); // hBox->addWidget(new QLabel(tr("AspectRatioMode"))); // auto wAspectRatioMode = new QComboBox(); // wAspectRatioMode->addItem(tr("IgnoreAspectRatio")); // wAspectRatioMode->addItem(tr("KeepAspectRatio")); // wAspectRatioMode->addItem(tr("KeepAspectRatioByExpanding")); // wAspectRatioMode->setCurrentIndex(aspectRatioMode); // connect(wAspectRatioMode, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int value) { // aspectRatioMode = value; // }); // hBox->addWidget(wAspectRatioMode); // hBox->addStretch(); // vBox->addLayout(hBox); hBox = new QHBoxLayout(); hBox->addWidget(new QLabel(tr("Play Properties"))); line = new QFrame(); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); hBox->addWidget(line, 1); vBox->addLayout(hBox); hBox = new QHBoxLayout(); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("Play Times"))); auto wPlayTimes = new QSpinBox(); wPlayTimes->setRange(1, 99999); wPlayTimes->setValue(playTimes); connect(wPlayTimes, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { playTimes = value; }); hBox->addWidget(wPlayTimes); hBox->addStretch(); vBox->addLayout(hBox); vBox->addStretch(); return wgtAttr; } bool EVideo::save(const QString &pageDir) { QString saveFile = pageDir + "/" + mName; if(QFile::exists(saveFile)) return true; QString oldFile = mDir + PAGEDEL_SUFFIX "/" + mName; if(QFile::exists(oldFile)) ; else if(QFile::exists(oldFile = mDir + "/" + mName)) ; else return false; QFile(oldFile).copy(saveFile); mDir = pageDir; // if(gProgItem->maxLen) { // auto waitingDlg = new WaitingDlg(mPageItem->listWidget()->window(), "正在转码视频 ..."); // auto thread = new VideoSplitThread(mWidth, mHeight, gProgItem->maxLen, gProgItem->isVer ? gProgItem->mWidth : gProgItem->mHeight, gProgItem->partLens, gProgItem->isVer, pos(), saveFile.toUtf8()); // connect(thread, &VideoSplitThread::emErr, this, [=](QString err) { // waitingDlg->close(); // if(! err.isEmpty()) QMessageBox::critical(mPageItem->listWidget()->window(), "Video trans error", err+"\n"+saveFile); // }); // connect(thread, &VideoSplitThread::emProgress, this, [saveFile, waitingDlg](int progress) { // waitingDlg->fdText->setText(QString("正在转码视频 %1%").arg(progress)); // }); // thread->start(); // waitingDlg->exec(); // } return true; } JObj EVideo::attrJson() const { JObj obj{ {"elementType", "Video"}, {"path", mDir}, {"file", mName}, {"pathRaw", mRawDir}, {"fileRaw", mRawName}, {"playTimes", playTimes} }; addBaseAttr(obj); return obj; } QString EVideo::transcoding(QWidget *parent, QString rawFile, QString rawName, QString dir, int w, int h, AVCodecID codec_id) { // if(gProgItem->maxLen) { // auto outFile = dir+"/"+rawName; // QFile::copy(rawFile, outFile); // return outFile; // } QSettings settings; int rawMax = qMax(w, h); if(settings.value("VideoCompress").toBool() && rawMax > 1360 && (w > gProgItem->mWidth || h > gProgItem->mHeight)) { auto rate = 1280.0 / rawMax; w *= rate; h *= rate; qDebug()<<"Compressed Size"<().valueToKey(error))+" ("+QString::number(error)+")"); }); connect(&process, &QProcess::readyReadStandardOutput, &msgBox, [&process] { auto data = process.readAllStandardOutput(); qInfo()<<"EVideo::transcoding StandardOutput"; qInfo()< -1) dur = QTime::fromString(txt.mid(idx+10, 11)+"0", "HH:mm:ss.zzz").msecsSinceStartOfDay(); } else { int idx = txt.indexOf("time="); if(idx > -1) { auto cur = QTime::fromString(txt.mid(idx+5, 11)+"0", "HH:mm:ss.zzz").msecsSinceStartOfDay(); if(dur > 0) msgBox.setText(tr("Video Transcoding Progress")+": "+QString::number(cur*100/dur)+"% "); } else err.append(txt); } }); process.start("ffmpeg", {"-y", "-i", rawFile, "-vcodec", "h264", "-s", QString::number(w)+"x"+QString::number(h), "-profile:v", "main", "-b:v", QString::number(w*h/150)+"k", outFile}); msgBox.exec(); if(err.right(32).contains("Conversion failed!")) { QMessageBox::critical(parent, tr("Error"), err); return ""; } return outFile; }