UI: Add VOD track support in advanced output

Adds a VOD track option (specific to Twitch) that allows a user to
specify which audio track to use for their Twitch VODs, which uses a
separate encoder to encode the track. This allows users the ability to
choose what audio goes on their VOD, separately from the live stream.
master
jp9000 2020-11-01 01:54:27 -08:00
parent 5b8f89d86e
commit 6b81c106d8
7 changed files with 127 additions and 6 deletions

View File

@ -769,6 +769,7 @@ Basic.Settings.Output.Adv.Audio.Track3="Track 3"
Basic.Settings.Output.Adv.Audio.Track4="Track 4"
Basic.Settings.Output.Adv.Audio.Track5="Track 5"
Basic.Settings.Output.Adv.Audio.Track6="Track 6"
Basic.Settings.Output.Adv.TwitchVodTrack="Twitch VOD Track"
# basic mode 'output' settings - advanced section - recording subsection
Basic.Settings.Output.Adv.Recording="Recording"

View File

@ -1907,7 +1907,7 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QFormLayout" name="formLayout_7">
<layout class="QFormLayout" name="advOutTopLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>

View File

@ -1054,6 +1054,7 @@ bool SimpleOutput::ReplayBufferActive() const
struct AdvancedOutput : BasicOutputHandler {
OBSEncoder streamAudioEnc;
OBSEncoder streamArchiveEnc;
OBSEncoder aacTrack[MAX_AUDIO_MIXES];
OBSEncoder h264Streaming;
OBSEncoder h264Recording;
@ -1229,6 +1230,14 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
throw "Failed to create streaming audio encoder "
"(advanced output)";
id = "";
int vodTrack =
config_get_int(main->Config(), "AdvOut", "VodTrackIndex") - 1;
if (!CreateAACEncoder(streamArchiveEnc, id, GetAudioBitrate(vodTrack),
"avc_aac_archive", vodTrack))
throw "Failed to create archive audio encoder "
"(advanced output)";
startRecording.Connect(obs_output_get_signal_handler(fileOutput),
"start", OBSStartRecording, this);
stopRecording.Connect(obs_output_get_signal_handler(fileOutput), "stop",
@ -1280,6 +1289,18 @@ void AdvancedOutput::Update()
UpdateAudioSettings();
}
static inline bool ServiceSupportsVodTrack(const char *service)
{
static const char *vodTrackServices[] = {"Twitch"};
for (const char *vodTrackService : vodTrackServices) {
if (astrcmpi(vodTrackService, service) == 0)
return true;
}
return false;
}
inline void AdvancedOutput::SetupStreaming()
{
bool rescale = config_get_bool(main->Config(), "AdvOut", "Rescale");
@ -1461,6 +1482,8 @@ inline void AdvancedOutput::UpdateAudioSettings()
"ApplyServiceSettings");
int streamTrackIndex =
config_get_int(main->Config(), "AdvOut", "TrackIndex");
int vodTrackIndex =
config_get_int(main->Config(), "AdvOut", "VodTrackIndex");
obs_data_t *settings[MAX_AUDIO_MIXES];
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
@ -1481,18 +1504,23 @@ inline void AdvancedOutput::UpdateAudioSettings()
}
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
int track = (int)(i + 1);
obs_encoder_update(aacTrack[i], settings[i]);
if ((int)(i + 1) == streamTrackIndex) {
if (track == streamTrackIndex || track == vodTrackIndex) {
if (applyServiceSettings) {
obs_service_apply_encoder_settings(
main->GetService(), nullptr,
settings[i]);
}
obs_encoder_update(streamAudioEnc, settings[i]);
}
if (track == streamTrackIndex)
obs_encoder_update(streamAudioEnc, settings[i]);
if (track == vodTrackIndex)
obs_encoder_update(streamArchiveEnc, settings[i]);
obs_data_release(settings[i]);
}
}
@ -1505,6 +1533,7 @@ void AdvancedOutput::SetupOutputs()
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++)
obs_encoder_set_audio(aacTrack[i], obs_get_audio());
obs_encoder_set_audio(streamAudioEnc, obs_get_audio());
obs_encoder_set_audio(streamArchiveEnc, obs_get_audio());
SetupStreaming();
@ -1527,7 +1556,11 @@ int AdvancedOutput::GetAudioBitrate(size_t i) const
bool AdvancedOutput::SetupStreaming(obs_service_t *service)
{
int streamTrack =
config_get_int(main->Config(), "AdvOut", "TrackIndex") - 1;
config_get_int(main->Config(), "AdvOut", "TrackIndex");
bool vodTrackEnabled =
config_get_bool(main->Config(), "AdvOut", "VodTrackEnabled");
int vodTrackIndex =
config_get_int(main->Config(), "AdvOut", "VodTrackIndex");
if (!useStreamEncoder ||
(!ffmpegOutput && !obs_output_active(fileOutput))) {
@ -1609,7 +1642,7 @@ bool AdvancedOutput::SetupStreaming(obs_service_t *service)
streamAudioEnc = obs_audio_encoder_create(
id, "alt_audio_enc", nullptr,
streamTrack, nullptr);
streamTrack - 1, nullptr);
if (!streamAudioEnc)
return false;
@ -1626,6 +1659,23 @@ bool AdvancedOutput::SetupStreaming(obs_service_t *service)
obs_output_set_video_encoder(streamOutput, h264Streaming);
obs_output_set_audio_encoder(streamOutput, streamAudioEnc, 0);
const char *id = obs_service_get_id(service);
if (strcmp(id, "rtmp_custom") == 0) {
vodTrackEnabled = false;
} else {
obs_data_t *settings = obs_service_get_settings(service);
const char *service = obs_data_get_string(settings, "service");
if (!ServiceSupportsVodTrack(service))
vodTrackEnabled = false;
obs_data_release(settings);
}
if (vodTrackEnabled && streamTrack != vodTrackIndex)
obs_output_set_audio_encoder(streamOutput, streamArchiveEnc, 1);
else
obs_output_set_audio_encoder(streamOutput, nullptr, 1);
return true;
}

View File

@ -1301,6 +1301,7 @@ bool OBSBasic::InitBasicConfigDefaults()
true);
config_set_default_bool(basicConfig, "AdvOut", "UseRescale", false);
config_set_default_uint(basicConfig, "AdvOut", "TrackIndex", 1);
config_set_default_uint(basicConfig, "AdvOut", "VodTrackIndex", 2);
config_set_default_string(basicConfig, "AdvOut", "Encoder", "obs_x264");
config_set_default_string(basicConfig, "AdvOut", "RecType", "Standard");

View File

@ -71,6 +71,8 @@ void OBSBasicSettings::InitStreamPage()
SLOT(UpdateServerList()));
connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
SLOT(UpdateKeyLink()));
connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
SLOT(UpdateVodTrackSetting()));
connect(ui->customServer, SIGNAL(textChanged(const QString &)), this,
SLOT(UpdateKeyLink()));
connect(ui->customServer, SIGNAL(editingFinished(const QString &)),
@ -141,6 +143,7 @@ void OBSBasicSettings::LoadStream1Settings()
UpdateKeyLink();
UpdateMoreInfoLink();
UpdateVodTrackSetting();
bool streamActive = obs_frontend_streaming_active();
ui->streamPage->setEnabled(!streamActive);
@ -594,3 +597,56 @@ void OBSBasicSettings::on_useAuth_toggled()
ui->authPwLabel->setVisible(use_auth);
ui->authPwWidget->setVisible(use_auth);
}
void OBSBasicSettings::UpdateVodTrackSetting()
{
bool enableVodTrack = ui->service->currentText() == "Twitch";
bool wasEnabled = !!vodTrackCheckbox;
if (enableVodTrack == wasEnabled)
return;
if (!enableVodTrack) {
delete vodTrackCheckbox;
delete vodTrackContainer;
return;
}
vodTrackCheckbox = new QCheckBox(
QTStr("Basic.Settings.Output.Adv.TwitchVodTrack"));
vodTrackCheckbox->setLayoutDirection(Qt::RightToLeft);
vodTrackContainer = new QWidget();
QHBoxLayout *vodTrackLayout = new QHBoxLayout();
for (int i = 0; i < MAX_AUDIO_MIXES; i++) {
vodTrack[i] = new QRadioButton(QString::number(i + 1));
vodTrackLayout->addWidget(vodTrack[i]);
HookWidget(vodTrack[i], SIGNAL(clicked(bool)),
SLOT(OutputsChanged()));
}
HookWidget(vodTrackCheckbox, SIGNAL(clicked(bool)),
SLOT(OutputsChanged()));
vodTrackLayout->addStretch();
vodTrackLayout->setContentsMargins(0, 0, 0, 0);
vodTrackContainer->setLayout(vodTrackLayout);
ui->advOutTopLayout->insertRow(2, vodTrackCheckbox, vodTrackContainer);
bool vodTrackEnabled =
config_get_bool(main->Config(), "AdvOut", "VodTrackEnabled");
vodTrackCheckbox->setChecked(vodTrackEnabled);
vodTrackContainer->setEnabled(vodTrackEnabled);
connect(vodTrackCheckbox, SIGNAL(clicked(bool)), vodTrackContainer,
SLOT(setEnabled(bool)));
int trackIndex =
config_get_int(main->Config(), "AdvOut", "VodTrackIndex");
for (int i = 0; i < MAX_AUDIO_MIXES; i++) {
vodTrack[i]->setChecked((i + 1) == trackIndex);
}
}

View File

@ -3386,6 +3386,13 @@ void OBSBasicSettings::SaveOutputSettings()
SaveEdit(ui->advOutTrack5Name, "AdvOut", "Track5Name");
SaveEdit(ui->advOutTrack6Name, "AdvOut", "Track6Name");
if (vodTrackCheckbox) {
SaveCheckBox(vodTrackCheckbox, "AdvOut", "VodTrackEnabled");
SaveTrackIndex(main->Config(), "AdvOut", "VodTrackIndex",
vodTrack[0], vodTrack[1], vodTrack[2],
vodTrack[3], vodTrack[4], vodTrack[5]);
}
SaveCheckBox(ui->advReplayBuf, "AdvOut", "RecRB");
SaveSpinBox(ui->advRBSecMax, "AdvOut", "RecRBTime");
SaveSpinBox(ui->advRBMegsMax, "AdvOut", "RecRBSize");

View File

@ -32,6 +32,7 @@
class OBSBasic;
class QAbstractButton;
class QRadioButton;
class QComboBox;
class QCheckBox;
class QLabel;
@ -156,6 +157,10 @@ private:
uint32_t outputCX = 0;
uint32_t outputCY = 0;
QPointer<QCheckBox> vodTrackCheckbox;
QPointer<QWidget> vodTrackContainer;
QPointer<QRadioButton> vodTrack[MAX_AUDIO_MIXES];
void SaveCombo(QComboBox *widget, const char *section,
const char *value);
void SaveComboData(QComboBox *widget, const char *section,
@ -239,6 +244,7 @@ private:
private slots:
void UpdateServerList();
void UpdateKeyLink();
void UpdateVodTrackSetting();
void UpdateMoreInfoLink();
void on_show_clicked();
void on_authPwShow_clicked();