Refactor downloader and file manager for improved rclone integration and add healthcheck and smoke test options
- Renamed download flags in ContentDownloader for clarity. - Enhanced FileManager with methods to build upload paths and verify existing files for rclone uploads. - Updated StreamProcessor to return success status for stream processing. - Added rclone smoke test and healthcheck functions to validate configuration and tool availability. - Improved environment variable handling with a utility function. - Updated TwitchArchive to incorporate new rclone verification and processing logic. - Added unit tests for new functionality and refactored existing tests for clarity and coverage. Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
parent
e92f36474a
commit
f97e0200d6
23 changed files with 1013 additions and 289 deletions
|
|
@ -17,49 +17,39 @@
|
|||
</div>
|
||||
|
||||
<div class="card">
|
||||
<label title="Set a quality override for this streamer">Quality</label>
|
||||
<InputCheckbox Value="overrideQuality" ValueChanged="@( (bool v) => overrideQuality = v )" ValueExpression="() => overrideQuality" title="Override default quality" /> Override
|
||||
<InputText @bind="model.Quality" disabled="@(!overrideQuality)" placeholder="@(global?.DefaultQuality ?? "")" title="Enter a quality string (e.g., best, 720p)" />
|
||||
<label title="Quality for this streamer">Quality</label>
|
||||
<InputText @bind-Value="model.Quality" placeholder="@(global?.DefaultQuality ?? "")" title="Enter a quality string (e.g., best, 720p)" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label title="Toggle cloud upload for this streamer">Upload to Cloud</label>
|
||||
<InputCheckbox Value="overrideUpload" ValueChanged="@( (bool v) => overrideUpload = v )" ValueExpression="() => overrideUpload" title="Override upload-to-cloud setting" /> Override
|
||||
<InputCheckbox Value="uploadToCloudVal" ValueChanged="@( (bool v) => uploadToCloudVal = v )" ValueExpression="() => uploadToCloudVal" disabled="@(!overrideUpload)" title="Upload to configured cloud destination" />
|
||||
<InputCheckbox Value="uploadToCloudVal" ValueChanged="@( (bool v) => uploadToCloudVal = v )" ValueExpression="() => uploadToCloudVal" title="Upload to configured cloud destination" />
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<label title="Cloud destination (e.g., rclone remote) for this streamer">Upload Destination</label>
|
||||
<InputText @bind="model.UploadDestination" title="Cloud destination (e.g., rclone remote)" />
|
||||
<InputText @bind-Value="model.UploadDestination" title="Cloud destination (e.g., rclone remote)" />
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<label title="Optional: override system Streamlink path for this streamer">Streamlink Path (override)</label>
|
||||
<InputCheckbox Value="overrideStreamlink" ValueChanged="@( (bool v) => overrideStreamlink = v )" ValueExpression="() => overrideStreamlink" title="Override streamlink path" /> Override
|
||||
<InputText @bind="model.StreamlinkPath" disabled="@(!overrideStreamlink)" placeholder="@(global?.StreamlinkPath ?? "")" title="Full path to streamlink executable" />
|
||||
</div>
|
||||
@* Streamlink path is global-only; not configurable per-streamer *@
|
||||
|
||||
<div class="card">
|
||||
<h4>Per-streamer overrides</h4>
|
||||
<h4>Per-streamer settings</h4>
|
||||
<div>
|
||||
<label>Download VOD</label>
|
||||
<InputCheckbox Value="overrideDownloadVOD" ValueChanged="@( (bool v) => overrideDownloadVOD = v )" ValueExpression="() => overrideDownloadVOD" /> Override
|
||||
<InputCheckbox Value="downloadVODVal" ValueChanged="@( (bool v) => downloadVODVal = v )" ValueExpression="() => downloadVODVal" disabled="@(!overrideDownloadVOD)" />
|
||||
<InputCheckbox Value="downloadVODVal" ValueChanged="@( (bool v) => downloadVODVal = v )" ValueExpression="() => downloadVODVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Download CHAT</label>
|
||||
<InputCheckbox Value="overrideDownloadCHAT" ValueChanged="@( (bool v) => overrideDownloadCHAT = v )" ValueExpression="() => overrideDownloadCHAT" /> Override
|
||||
<InputCheckbox Value="downloadCHATVal" ValueChanged="@( (bool v) => downloadCHATVal = v )" ValueExpression="() => downloadCHATVal" disabled="@(!overrideDownloadCHAT)" />
|
||||
<InputCheckbox Value="downloadCHATVal" ValueChanged="@( (bool v) => downloadCHATVal = v )" ValueExpression="() => downloadCHATVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Merge Video & Chat</label>
|
||||
<InputCheckbox Value="overrideMergeVideoChat" ValueChanged="@( (bool v) => overrideMergeVideoChat = v )" ValueExpression="() => overrideMergeVideoChat" /> Override
|
||||
<InputCheckbox Value="mergeVideoChatVal" ValueChanged="@( (bool v) => mergeVideoChatVal = v )" ValueExpression="() => mergeVideoChatVal" disabled="@(!overrideMergeVideoChat)" />
|
||||
<InputCheckbox Value="mergeVideoChatVal" ValueChanged="@( (bool v) => mergeVideoChatVal = v )" ValueExpression="() => mergeVideoChatVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Merge Chat Layout</label>
|
||||
<InputCheckbox Value="overrideMergeChatLayout" ValueChanged="@( (bool v) => overrideMergeChatLayout = v )" ValueExpression="() => overrideMergeChatLayout" /> Override
|
||||
<InputSelect @bind-Value="mergeChatLayoutVal" disabled="@(!overrideMergeChatLayout)">
|
||||
<InputSelect @bind-Value="mergeChatLayoutVal">
|
||||
<option value="side-by-side">Side by side</option>
|
||||
<option value="stacked">Stacked</option>
|
||||
<option value="overlay">Overlay</option>
|
||||
|
|
@ -67,105 +57,35 @@
|
|||
</div>
|
||||
<div>
|
||||
<label>VOD Timeout (sec)</label>
|
||||
<InputCheckbox Value="overrideVodTimeout" ValueChanged="@( (bool v) => overrideVodTimeout = v )" ValueExpression="() => overrideVodTimeout" /> Override
|
||||
<InputNumber @bind-Value="vodTimeoutVal" disabled="@(!overrideVodTimeout)" />
|
||||
<InputNumber @bind-Value="vodTimeoutVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Delete Files</label>
|
||||
<InputCheckbox Value="overrideDeleteFiles" ValueChanged="@( (bool v) => overrideDeleteFiles = v )" ValueExpression="() => overrideDeleteFiles" /> Override
|
||||
<InputCheckbox Value="deleteFilesVal" ValueChanged="@( (bool v) => deleteFilesVal = v )" ValueExpression="() => deleteFilesVal" disabled="@(!overrideDeleteFiles)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>HLS Segments (live)</label>
|
||||
<InputCheckbox Value="overrideHlsSegments" ValueChanged="@( (bool v) => overrideHlsSegments = v )" ValueExpression="() => overrideHlsSegments" /> Override
|
||||
<InputNumber @bind-Value="hlsSegmentsVal" disabled="@(!overrideHlsSegments)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>FFmpeg HW Accel</label>
|
||||
<InputCheckbox Value="overrideFfmpegHwaccel" ValueChanged="@( (bool v) => overrideFfmpegHwaccel = v )" ValueExpression="() => overrideFfmpegHwaccel" /> Override
|
||||
<InputSelect @bind-Value="ffmpegHwaccelVal" disabled="@(!overrideFfmpegHwaccel)">
|
||||
<option value="auto">Auto</option>
|
||||
<option value="none">None</option>
|
||||
<option value="vaapi">VAAPI</option>
|
||||
<option value="dxva2">DXVA2</option>
|
||||
<option value="qsv">QSV</option>
|
||||
<option value="cuda">CUDA</option>
|
||||
</InputSelect>
|
||||
</div>
|
||||
<div>
|
||||
<label>FFmpeg Threads</label>
|
||||
<InputCheckbox Value="overrideFfmpegThreads" ValueChanged="@( (bool v) => overrideFfmpegThreads = v )" ValueExpression="() => overrideFfmpegThreads" /> Override
|
||||
<InputNumber @bind-Value="ffmpegThreadsVal" disabled="@(!overrideFfmpegThreads)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>FFmpeg Audio Bitrate</label>
|
||||
<InputCheckbox Value="overrideFfmpegAudioBitrate" ValueChanged="@( (bool v) => overrideFfmpegAudioBitrate = v )" ValueExpression="() => overrideFfmpegAudioBitrate" /> Override
|
||||
<InputText @bind-Value="ffmpegAudioBitrateVal" disabled="@(!overrideFfmpegAudioBitrate)" />
|
||||
<InputCheckbox Value="deleteFilesVal" ValueChanged="@( (bool v) => deleteFilesVal = v )" ValueExpression="() => deleteFilesVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Download Live CHAT</label>
|
||||
<InputCheckbox Value="overrideDownloadLiveCHAT" ValueChanged="@( (bool v) => overrideDownloadLiveCHAT = v )" ValueExpression="() => overrideDownloadLiveCHAT" /> Override
|
||||
<InputCheckbox Value="downloadLiveCHATVal" ValueChanged="@( (bool v) => downloadLiveCHATVal = v )" ValueExpression="() => downloadLiveCHATVal" disabled="@(!overrideDownloadLiveCHAT)" />
|
||||
<InputCheckbox Value="downloadLiveCHATVal" ValueChanged="@( (bool v) => downloadLiveCHATVal = v )" ValueExpression="() => downloadLiveCHATVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Upload Pre-Merge Video</label>
|
||||
<InputCheckbox Value="overrideUploadPreMergeVideo" ValueChanged="@( (bool v) => overrideUploadPreMergeVideo = v )" ValueExpression="() => overrideUploadPreMergeVideo" /> Override
|
||||
<InputCheckbox Value="uploadPreMergeVideoVal" ValueChanged="@( (bool v) => uploadPreMergeVideoVal = v )" ValueExpression="() => uploadPreMergeVideoVal" disabled="@(!overrideUploadPreMergeVideo)" />
|
||||
<InputCheckbox Value="uploadPreMergeVideoVal" ValueChanged="@( (bool v) => uploadPreMergeVideoVal = v )" ValueExpression="() => uploadPreMergeVideoVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Upload Merged Video</label>
|
||||
<InputCheckbox Value="overrideUploadMergedVideo" ValueChanged="@( (bool v) => overrideUploadMergedVideo = v )" ValueExpression="() => overrideUploadMergedVideo" /> Override
|
||||
<InputCheckbox Value="uploadMergedVideoVal" ValueChanged="@( (bool v) => uploadMergedVideoVal = v )" ValueExpression="() => uploadMergedVideoVal" disabled="@(!overrideUploadMergedVideo)" />
|
||||
<InputCheckbox Value="uploadMergedVideoVal" ValueChanged="@( (bool v) => uploadMergedVideoVal = v )" ValueExpression="() => uploadMergedVideoVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Upload Chat Video</label>
|
||||
<InputCheckbox Value="overrideUploadChatVideo" ValueChanged="@( (bool v) => overrideUploadChatVideo = v )" ValueExpression="() => overrideUploadChatVideo" /> Override
|
||||
<InputCheckbox Value="uploadChatVideoVal" ValueChanged="@( (bool v) => uploadChatVideoVal = v )" ValueExpression="() => uploadChatVideoVal" disabled="@(!overrideUploadChatVideo)" />
|
||||
<InputCheckbox Value="uploadChatVideoVal" ValueChanged="@( (bool v) => uploadChatVideoVal = v )" ValueExpression="() => uploadChatVideoVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Only Raw</label>
|
||||
<InputCheckbox Value="overrideOnlyRaw" ValueChanged="@( (bool v) => overrideOnlyRaw = v )" ValueExpression="() => overrideOnlyRaw" /> Override
|
||||
<InputCheckbox Value="onlyRawVal" ValueChanged="@( (bool v) => onlyRawVal = v )" ValueExpression="() => onlyRawVal" disabled="@(!overrideOnlyRaw)" />
|
||||
<InputCheckbox Value="onlyRawVal" ValueChanged="@( (bool v) => onlyRawVal = v )" ValueExpression="() => onlyRawVal" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Clean Raw</label>
|
||||
<InputCheckbox Value="overrideCleanRaw" ValueChanged="@( (bool v) => overrideCleanRaw = v )" ValueExpression="() => overrideCleanRaw" /> Override
|
||||
<InputCheckbox Value="cleanRawVal" ValueChanged="@( (bool v) => cleanRawVal = v )" ValueExpression="() => cleanRawVal" disabled="@(!overrideCleanRaw)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>HLS Segments (VOD)</label>
|
||||
<InputCheckbox Value="overrideHlsSegmentsVOD" ValueChanged="@( (bool v) => overrideHlsSegmentsVOD = v )" ValueExpression="() => overrideHlsSegmentsVOD" /> Override
|
||||
<InputNumber @bind-Value="hlsSegmentsVODVal" disabled="@(!overrideHlsSegmentsVOD)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Streamlink ttvlol</label>
|
||||
<InputCheckbox Value="overrideStreamlinkTtvlol" ValueChanged="@( (bool v) => overrideStreamlinkTtvlol = v )" ValueExpression="() => overrideStreamlinkTtvlol" /> Override
|
||||
<InputCheckbox Value="streamlinkTtvlolVal" ValueChanged="@( (bool v) => streamlinkTtvlolVal = v )" ValueExpression="() => streamlinkTtvlolVal" disabled="@(!overrideStreamlinkTtvlol)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>FFmpeg Audio Codec</label>
|
||||
<InputCheckbox Value="overrideFfmpegAudioCodec" ValueChanged="@( (bool v) => overrideFfmpegAudioCodec = v )" ValueExpression="() => overrideFfmpegAudioCodec" /> Override
|
||||
<InputText @bind-Value="ffmpegAudioCodecVal" disabled="@(!overrideFfmpegAudioCodec)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>FFmpeg Audio Sample Rate</label>
|
||||
<InputCheckbox Value="overrideFfmpegAudioSamplerate" ValueChanged="@( (bool v) => overrideFfmpegAudioSamplerate = v )" ValueExpression="() => overrideFfmpegAudioSamplerate" /> Override
|
||||
<InputNumber @bind-Value="ffmpegAudioSamplerateVal" disabled="@(!overrideFfmpegAudioSamplerate)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>FFmpeg Error Recovery</label>
|
||||
<InputCheckbox Value="overrideFfmpegErrorRecovery" ValueChanged="@( (bool v) => overrideFfmpegErrorRecovery = v )" ValueExpression="() => overrideFfmpegErrorRecovery" /> Override
|
||||
<InputCheckbox Value="ffmpegErrorRecoveryVal" ValueChanged="@( (bool v) => ffmpegErrorRecoveryVal = v )" ValueExpression="() => ffmpegErrorRecoveryVal" disabled="@(!overrideFfmpegErrorRecovery)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>FFmpeg Faststart</label>
|
||||
<InputCheckbox Value="overrideFfmpegFaststart" ValueChanged="@( (bool v) => overrideFfmpegFaststart = v )" ValueExpression="() => overrideFfmpegFaststart" /> Override
|
||||
<InputCheckbox Value="ffmpegFaststartVal" ValueChanged="@( (bool v) => ffmpegFaststartVal = v )" ValueExpression="() => ffmpegFaststartVal" disabled="@(!overrideFfmpegFaststart)" />
|
||||
</div>
|
||||
<div>
|
||||
<label>FFmpeg Progress</label>
|
||||
<InputCheckbox Value="overrideFfmpegProgress" ValueChanged="@( (bool v) => overrideFfmpegProgress = v )" ValueExpression="() => overrideFfmpegProgress" /> Override
|
||||
<InputCheckbox Value="ffmpegProgressVal" ValueChanged="@( (bool v) => ffmpegProgressVal = v )" ValueExpression="() => ffmpegProgressVal" disabled="@(!overrideFfmpegProgress)" />
|
||||
<InputCheckbox Value="cleanRawVal" ValueChanged="@( (bool v) => cleanRawVal = v )" ValueExpression="() => cleanRawVal" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -193,37 +113,10 @@
|
|||
@code {
|
||||
[Parameter]
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
private TwitchArchive.Core.Config.StreamerConfig model = new();
|
||||
private TwitchArchive.Core.Config.GlobalConfig? global;
|
||||
private bool saved = false;
|
||||
private bool showConfirm = false;
|
||||
private bool overrideQuality = false;
|
||||
private bool overrideUpload = false;
|
||||
private bool overrideStreamlink = false;
|
||||
private bool overrideDownloadVOD = false;
|
||||
private bool overrideDownloadCHAT = false;
|
||||
private bool overrideMergeVideoChat = false;
|
||||
private bool overrideMergeChatLayout = false;
|
||||
private bool overrideVodTimeout = false;
|
||||
private bool overrideDeleteFiles = false;
|
||||
private bool overrideHlsSegments = false;
|
||||
private bool overrideFfmpegHwaccel = false;
|
||||
private bool overrideFfmpegThreads = false;
|
||||
private bool overrideFfmpegAudioBitrate = false;
|
||||
private bool overrideDownloadLiveCHAT = false;
|
||||
private bool overrideUploadPreMergeVideo = false;
|
||||
private bool overrideUploadMergedVideo = false;
|
||||
private bool overrideUploadChatVideo = false;
|
||||
private bool overrideOnlyRaw = false;
|
||||
private bool overrideCleanRaw = false;
|
||||
private bool overrideHlsSegmentsVOD = false;
|
||||
private bool overrideStreamlinkTtvlol = false;
|
||||
private bool overrideFfmpegAudioCodec = false;
|
||||
private bool overrideFfmpegAudioSamplerate = false;
|
||||
private bool overrideFfmpegErrorRecovery = false;
|
||||
private bool overrideFfmpegFaststart = false;
|
||||
private bool overrideFfmpegProgress = false;
|
||||
|
||||
// local values for nullable per-streamer settings (bind safely)
|
||||
private bool downloadVODVal;
|
||||
|
|
@ -233,28 +126,18 @@
|
|||
private string mergeChatLayoutVal = "side-by-side";
|
||||
private int? vodTimeoutVal;
|
||||
private bool deleteFilesVal;
|
||||
private int? hlsSegmentsVal;
|
||||
private string ffmpegHwaccelVal = "auto";
|
||||
private int? ffmpegThreadsVal;
|
||||
private string? ffmpegAudioBitrateVal;
|
||||
private bool uploadPreMergeVideoVal;
|
||||
private bool uploadMergedVideoVal;
|
||||
private bool uploadChatVideoVal;
|
||||
private bool onlyRawVal;
|
||||
private bool cleanRawVal;
|
||||
private int? hlsSegmentsVODVal;
|
||||
private bool streamlinkTtvlolVal;
|
||||
private string? ffmpegAudioCodecVal;
|
||||
private int? ffmpegAudioSamplerateVal;
|
||||
private bool ffmpegErrorRecoveryVal;
|
||||
private bool ffmpegFaststartVal;
|
||||
private bool ffmpegProgressVal;
|
||||
private bool uploadToCloudVal;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
global = ConfigService.LoadGlobal();
|
||||
var s = ConfigService.LoadStreamer(Username);
|
||||
var isNew = s == null;
|
||||
if (s != null) model = s;
|
||||
// initialize local values from model or global defaults
|
||||
downloadVODVal = model.DownloadVOD ?? global?.Defaults.DownloadVOD ?? true;
|
||||
|
|
@ -264,57 +147,67 @@
|
|||
mergeChatLayoutVal = model.MergeChatLayout ?? global?.Defaults.MergeChatLayout ?? "side-by-side";
|
||||
vodTimeoutVal = model.VodTimeout ?? global?.Defaults.VodTimeout ?? 300;
|
||||
deleteFilesVal = model.DeleteFiles ?? global?.Defaults.DeleteFiles ?? false;
|
||||
hlsSegmentsVal = model.HlsSegments ?? global?.Defaults.HlsSegments ?? 3;
|
||||
ffmpegHwaccelVal = model.FfmpegHwaccel ?? global?.Defaults.FfmpegHwaccel ?? "auto";
|
||||
ffmpegThreadsVal = model.FfmpegThreads ?? global?.Defaults.FfmpegThreads ?? 0;
|
||||
ffmpegAudioBitrateVal = model.FfmpegAudioBitrate ?? global?.Defaults.FfmpegAudioBitrate ?? "192k";
|
||||
uploadPreMergeVideoVal = model.UploadPreMergeVideo ?? global?.Defaults.UploadPreMergeVideo ?? true;
|
||||
uploadMergedVideoVal = model.UploadMergedVideo ?? global?.Defaults.UploadMergedVideo ?? true;
|
||||
uploadChatVideoVal = model.UploadChatVideo ?? global?.Defaults.UploadChatVideo ?? false;
|
||||
onlyRawVal = model.OnlyRaw ?? global?.Defaults.OnlyRaw ?? false;
|
||||
cleanRawVal = model.CleanRaw ?? global?.Defaults.CleanRaw ?? true;
|
||||
hlsSegmentsVODVal = model.HlsSegmentsVOD ?? global?.Defaults.HlsSegmentsVOD ?? 10;
|
||||
streamlinkTtvlolVal = model.StreamlinkTtvlol ?? global?.Defaults.StreamlinkTtvlol ?? false;
|
||||
ffmpegAudioCodecVal = model.FfmpegAudioCodec ?? global?.Defaults.FfmpegAudioCodec ?? "aac";
|
||||
ffmpegAudioSamplerateVal = model.FfmpegAudioSamplerate ?? global?.Defaults.FfmpegAudioSamplerate ?? 48000;
|
||||
ffmpegErrorRecoveryVal = model.FfmpegErrorRecovery ?? global?.Defaults.FfmpegErrorRecovery ?? true;
|
||||
ffmpegFaststartVal = model.FfmpegFaststart ?? global?.Defaults.FfmpegFaststart ?? true;
|
||||
ffmpegProgressVal = model.FfmpegProgress ?? global?.Defaults.FfmpegProgress ?? false;
|
||||
uploadToCloudVal = model.UploadToCloud ?? global?.UploadToCloud ?? false;
|
||||
|
||||
// when creating a new streamer config, populate model with global defaults so
|
||||
// the streamer config stores initial values and subsequent edits use streamer values
|
||||
if (isNew)
|
||||
{
|
||||
model.Quality = model.Quality ?? global?.DefaultQuality;
|
||||
model.UploadToCloud = uploadToCloudVal;
|
||||
model.UploadDestination = model.UploadDestination ?? global?.UploadDestination;
|
||||
model.DownloadVOD = downloadVODVal;
|
||||
model.DownloadCHAT = downloadCHATVal;
|
||||
model.DownloadLiveCHAT = downloadLiveCHATVal;
|
||||
model.MergeVideoChat = mergeVideoChatVal;
|
||||
model.MergeChatLayout = mergeChatLayoutVal;
|
||||
model.VodTimeout = vodTimeoutVal;
|
||||
model.DeleteFiles = deleteFilesVal;
|
||||
model.UploadPreMergeVideo = uploadPreMergeVideoVal;
|
||||
model.UploadMergedVideo = uploadMergedVideoVal;
|
||||
model.UploadChatVideo = uploadChatVideoVal;
|
||||
model.OnlyRaw = onlyRawVal;
|
||||
model.CleanRaw = cleanRawVal;
|
||||
}
|
||||
}
|
||||
|
||||
private void Save()
|
||||
{
|
||||
model.Username = Username;
|
||||
if (!overrideQuality) model.Quality = null;
|
||||
if (string.IsNullOrWhiteSpace(model.Quality)) model.Quality = null;
|
||||
// Upload to cloud
|
||||
model.UploadToCloud = overrideUpload ? uploadToCloudVal : (bool?)null;
|
||||
// Streamlink path
|
||||
model.StreamlinkPath = overrideStreamlink ? model.StreamlinkPath : null;
|
||||
// Per-streamer values: map local values when overridden, otherwise clear
|
||||
model.DownloadVOD = overrideDownloadVOD ? downloadVODVal : (bool?)null;
|
||||
model.DownloadCHAT = overrideDownloadCHAT ? downloadCHATVal : (bool?)null;
|
||||
model.DownloadLiveCHAT = overrideDownloadLiveCHAT ? downloadLiveCHATVal : (bool?)null;
|
||||
model.MergeVideoChat = overrideMergeVideoChat ? mergeVideoChatVal : (bool?)null;
|
||||
model.MergeChatLayout = overrideMergeChatLayout ? mergeChatLayoutVal : null;
|
||||
model.VodTimeout = overrideVodTimeout ? vodTimeoutVal : (int?)null;
|
||||
model.DeleteFiles = overrideDeleteFiles ? deleteFilesVal : (bool?)null;
|
||||
model.HlsSegments = overrideHlsSegments ? hlsSegmentsVal : (int?)null;
|
||||
model.FfmpegHwaccel = overrideFfmpegHwaccel ? ffmpegHwaccelVal : null;
|
||||
model.FfmpegThreads = overrideFfmpegThreads ? ffmpegThreadsVal : (int?)null;
|
||||
model.FfmpegAudioBitrate = overrideFfmpegAudioBitrate ? ffmpegAudioBitrateVal : null;
|
||||
model.UploadPreMergeVideo = overrideUploadPreMergeVideo ? uploadPreMergeVideoVal : (bool?)null;
|
||||
model.UploadMergedVideo = overrideUploadMergedVideo ? uploadMergedVideoVal : (bool?)null;
|
||||
model.UploadChatVideo = overrideUploadChatVideo ? uploadChatVideoVal : (bool?)null;
|
||||
model.OnlyRaw = overrideOnlyRaw ? onlyRawVal : (bool?)null;
|
||||
model.CleanRaw = overrideCleanRaw ? cleanRawVal : (bool?)null;
|
||||
model.HlsSegmentsVOD = overrideHlsSegmentsVOD ? hlsSegmentsVODVal : (int?)null;
|
||||
model.StreamlinkTtvlol = overrideStreamlinkTtvlol ? streamlinkTtvlolVal : (bool?)null;
|
||||
model.FfmpegAudioCodec = overrideFfmpegAudioCodec ? ffmpegAudioCodecVal : null;
|
||||
model.FfmpegAudioSamplerate = overrideFfmpegAudioSamplerate ? ffmpegAudioSamplerateVal : (int?)null;
|
||||
model.FfmpegErrorRecovery = overrideFfmpegErrorRecovery ? ffmpegErrorRecoveryVal : (bool?)null;
|
||||
model.FfmpegFaststart = overrideFfmpegFaststart ? ffmpegFaststartVal : (bool?)null;
|
||||
model.FfmpegProgress = overrideFfmpegProgress ? ffmpegProgressVal : (bool?)null;
|
||||
model.UploadToCloud = uploadToCloudVal;
|
||||
// Ensure global-only settings are not stored per-streamer
|
||||
model.StreamlinkPath = null;
|
||||
model.HlsSegments = null;
|
||||
model.HlsSegmentsVOD = null;
|
||||
model.StreamlinkTtvlol = null;
|
||||
model.FfmpegHwaccel = null;
|
||||
model.FfmpegThreads = null;
|
||||
model.FfmpegAudioBitrate = null;
|
||||
model.FfmpegAudioCodec = null;
|
||||
model.FfmpegAudioSamplerate = null;
|
||||
model.FfmpegErrorRecovery = null;
|
||||
model.FfmpegFaststart = null;
|
||||
model.FfmpegProgress = null;
|
||||
// Per-streamer values: always map local values into the model
|
||||
model.DownloadVOD = downloadVODVal;
|
||||
model.DownloadCHAT = downloadCHATVal;
|
||||
model.DownloadLiveCHAT = downloadLiveCHATVal;
|
||||
model.MergeVideoChat = mergeVideoChatVal;
|
||||
model.MergeChatLayout = mergeChatLayoutVal;
|
||||
model.VodTimeout = vodTimeoutVal;
|
||||
model.DeleteFiles = deleteFilesVal;
|
||||
model.UploadPreMergeVideo = uploadPreMergeVideoVal;
|
||||
model.UploadMergedVideo = uploadMergedVideoVal;
|
||||
model.UploadChatVideo = uploadChatVideoVal;
|
||||
model.OnlyRaw = onlyRawVal;
|
||||
model.CleanRaw = cleanRawVal;
|
||||
ConfigService.SaveStreamer(model);
|
||||
saved = true;
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue