攝像頭範例

Shows how to capture a still image or record video. or video.

攝像頭範例演示如何使用 Qt Multimedia 實現一些基本攝像頭功能以獲得靜止圖像和錄製帶音頻的視頻剪輯。

運行範例

要運行範例從 Qt Creator ,打開 Welcome 模式,然後選擇範例從 Examples 。更多信息,拜訪 構建和運行範例 .

The example implements a Camera class that acts as our camera interface. It has a user interface, control functions, setting values and a means of defining the location where the image or video clip is to be saved. It will also store the image and video settings.

The Camera class uses:

  • 實例化的 QCamera , the API class interface to the hardware.
  • 實例化的 QImageCapture to take still images.
  • 實例化的 QMediaRecorder to record video. It also contains the user interface object.

The Camera constructor

The Camera constructor does some basic initialization of the user interface including disabling all buttons by default.

Camera::Camera() : ui(new Ui::Camera)
{
    ui->setupUi(this);
    m_audioInput.reset(new QAudioInput);
    m_captureSession.setAudioInput(m_audioInput.get());
    // Camera devices:
    videoDevicesGroup = new QActionGroup(this);
    videoDevicesGroup->setExclusive(true);
    updateCameras();
    connect(&m_devices, &QMediaDevices::videoInputsChanged, this, &Camera::updateCameras);
    connect(videoDevicesGroup, &QActionGroup::triggered, this, &Camera::updateCameraDevice);
    connect(ui->captureWidget, &QTabWidget::currentChanged, this, &Camera::updateCaptureMode);
    connect(ui->metaDataButton, &QPushButton::clicked, this, &Camera::showMetaDataDialog);
    connect(ui->exposureCompensation, &QAbstractSlider::valueChanged, this,
            &Camera::setExposureCompensation);
    setCamera(QMediaDevices::defaultVideoInput());
}
void Camera::setCamera(const QCameraDevice &cameraDevice)
{
    m_camera.reset(new QCamera(cameraDevice));
    m_captureSession.setCamera(m_camera.data());
    connect(m_camera.data(), &QCamera::activeChanged, this, &Camera::updateCameraActive);
    connect(m_camera.data(), &QCamera::errorOccurred, this, &Camera::displayCameraError);
    if (!m_mediaRecorder) {
        m_mediaRecorder.reset(new QMediaRecorder);
        m_captureSession.setRecorder(m_mediaRecorder.data());
        connect(m_mediaRecorder.data(), &QMediaRecorder::recorderStateChanged, this,
                &Camera::updateRecorderState);
        connect(m_mediaRecorder.data(), &QMediaRecorder::durationChanged, this,
                &Camera::updateRecordTime);
        connect(m_mediaRecorder.data(), &QMediaRecorder::errorChanged, this,
                &Camera::displayRecorderError);
    }
    if (!m_imageCapture) {
        m_imageCapture.reset(new QImageCapture);
        m_captureSession.setImageCapture(m_imageCapture.get());
        connect(m_imageCapture.get(), &QImageCapture::readyForCaptureChanged, this,
                &Camera::readyForCapture);
        connect(m_imageCapture.get(), &QImageCapture::imageCaptured, this,
                &Camera::processCapturedImage);
        connect(m_imageCapture.get(), &QImageCapture::imageSaved, this, &Camera::imageSaved);
        connect(m_imageCapture.get(), &QImageCapture::errorOccurred, this,
                &Camera::displayCaptureError);
    }
    m_captureSession.setVideoOutput(ui->viewfinder);
    updateCameraActive(m_camera->isActive());
    updateRecorderState(m_mediaRecorder->recorderState());
    readyForCapture(m_imageCapture->isReadyForCapture());
    updateCaptureMode();
    m_camera->start();
}
void Camera::keyPressEvent(QKeyEvent *event)
{
    if (event->isAutoRepeat())
        return;
    switch (event->key()) {
    case Qt::Key_CameraFocus:
        displayViewfinder();
        event->accept();
        break;
    case Qt::Key_Camera:
        if (m_doImageCapture) {
            takeImage();
        } else {
            if (m_mediaRecorder->recorderState() == QMediaRecorder::RecordingState)
                stop();
            else
                record();
        }
        event->accept();
        break;
    default:
        QMainWindow::keyPressEvent(event);
    }
}
void Camera::updateRecordTime()
{
    QString str = tr("Recorded %1 sec").arg(m_mediaRecorder->duration() / 1000);
    ui->statusbar->showMessage(str);
}
void Camera::processCapturedImage(int requestId, const QImage &img)
{
    Q_UNUSED(requestId);
    QImage scaledImage =
            img.scaled(ui->viewfinder->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    ui->lastImagePreviewLabel->setPixmap(QPixmap::fromImage(scaledImage));
    // Display captured image for 4 seconds.
    displayCapturedImage();
    QTimer::singleShot(4000, this, &Camera::displayViewfinder);
}
void Camera::configureCaptureSettings()
{
    if (m_doImageCapture)
        configureImageSettings();
    else
        configureVideoSettings();
}
void Camera::configureVideoSettings()
{
    VideoSettings settingsDialog(m_mediaRecorder.data());
    if (settingsDialog.exec())
        settingsDialog.applySettings();
}
void Camera::configureImageSettings()
{
    ImageSettings settingsDialog(m_imageCapture.get());
    if (settingsDialog.exec() == QDialog::Accepted)
        settingsDialog.applyImageSettings();
}
void Camera::record()
{
    m_mediaRecorder->record();
    updateRecordTime();
}
void Camera::pause()
{
    m_mediaRecorder->pause();
}
void Camera::stop()
{
    m_mediaRecorder->stop();
}
void Camera::setMuted(bool muted)
{
    m_captureSession.audioInput()->setMuted(muted);
}
void Camera::takeImage()
{
    m_isCapturingImage = true;
    m_imageCapture->captureToFile();
}
void Camera::displayCaptureError(int id, const QImageCapture::Error error,
                                 const QString &errorString)
{
    Q_UNUSED(id);
    Q_UNUSED(error);
    QMessageBox::warning(this, tr("Image Capture Error"), errorString);
    m_isCapturingImage = false;
}
void Camera::startCamera()
{
    m_camera->start();
}
void Camera::stopCamera()
{
    m_camera->stop();
}
void Camera::updateCaptureMode()
{
    int tabIndex = ui->captureWidget->currentIndex();
    m_doImageCapture = (tabIndex == 0);
}
void Camera::updateCameraActive(bool active)
{
    if (active) {
        ui->actionStartCamera->setEnabled(false);
        ui->actionStopCamera->setEnabled(true);
        ui->captureWidget->setEnabled(true);
        ui->actionSettings->setEnabled(true);
    } else {
        ui->actionStartCamera->setEnabled(true);
        ui->actionStopCamera->setEnabled(false);
        ui->captureWidget->setEnabled(false);
        ui->actionSettings->setEnabled(false);
    }
}
void Camera::updateRecorderState(QMediaRecorder::RecorderState state)
{
    switch (state) {
    case QMediaRecorder::StoppedState:
        ui->recordButton->setEnabled(true);
        ui->pauseButton->setEnabled(true);
        ui->stopButton->setEnabled(false);
        ui->metaDataButton->setEnabled(true);
        break;
    case QMediaRecorder::PausedState:
        ui->recordButton->setEnabled(true);
        ui->pauseButton->setEnabled(false);
        ui->stopButton->setEnabled(true);
        ui->metaDataButton->setEnabled(false);
					

It seeks permissions for input device access:

Inputs are assigned:

UI signals are connected to slots that react to the triggering event:

However, most of the work is done when the setCamera() function is called, passing in a QCameraDevice .

setCamera()

setCamera() sets up various connections between the user interface and the functionality of the Camera class using signals and slots. It also instantiates and initializes the QCamera , QImageCapture ,和 QMediaRecorder 對象。

The still and video recording visual tabs are enabled:

Finally the start () function of the QCamera object is called.

Triggering capturing

Now that the camera is ready for user commands it waits for a suitable event. Such an event can be a key press of either the Qt::Key_CameraFocus or Qt::Key_Camera buttons on the application window.

Key_CameraFocus will simply display the preview and lock the camera settings.

Key_Camera will either call takeImage() if doing an image capture, or call record() or stop() (if already recording) on the QMediaRecorder instance when recording video.

範例工程 @ code.qt.io