Broadcast Text pull-out (Live screen) + launch geometry 1920x1040/1366x768 with restore
This commit is contained in:
@@ -2,9 +2,9 @@ using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using ytLive.Models;
|
||||
using AppLog = ytLive.Helpers.AppLog;
|
||||
|
||||
namespace ytLive.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Manages YouTube live stream lifecycle — create broadcasts,
|
||||
/// bind stream keys, monitor health.
|
||||
@@ -79,6 +79,51 @@ public class YouTubeStreamService
|
||||
return details;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pushes the creator-editable broadcast fields to YouTube via
|
||||
/// liveBroadcasts.update (part=snippet,status). Valid any time, including
|
||||
/// while live. Returns null on success, otherwise a human-readable error.
|
||||
/// Note: liveBroadcasts.update REPLACES the snippet part, so scheduledStartTime
|
||||
/// is re-sent unchanged from the stored value — omitting it would clear the
|
||||
/// schedule server-side.
|
||||
/// </summary>
|
||||
public async Task<string?> UpdateBroadcast(string broadcastId, BroadcastMetadata meta)
|
||||
{
|
||||
if (!await EnsureToken()) return "not signed in";
|
||||
|
||||
var tags = meta.TagsCsv
|
||||
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.ToList();
|
||||
|
||||
var broadcast = new
|
||||
{
|
||||
id = broadcastId,
|
||||
snippet = new
|
||||
{
|
||||
title = meta.Title,
|
||||
description = meta.Description,
|
||||
tags = tags,
|
||||
// update replaces the whole snippet part; echo the original schedule
|
||||
scheduledStartTime = (meta.ScheduledStartTime ?? DateTime.UtcNow).ToString("o"),
|
||||
categoryId = "22"
|
||||
},
|
||||
status = new
|
||||
{
|
||||
privacyStatus = string.IsNullOrWhiteSpace(meta.Visibility) ? "private" : meta.Visibility.ToLowerInvariant(),
|
||||
selfDeclaredMadeForKids = meta.MadeForKids
|
||||
}
|
||||
};
|
||||
|
||||
_http.DefaultRequestHeaders.Authorization = new("Bearer", _auth.CurrentChannel!.AccessToken);
|
||||
var response = await _http.PutAsJsonAsync(
|
||||
$"{ApiBase}/liveBroadcasts?part=snippet,status", broadcast);
|
||||
|
||||
if (response.IsSuccessStatusCode) return null;
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
AppLog.Write($"Broadcast update failed ({(int)response.StatusCode}): {body}");
|
||||
return $"YouTube rejected the update ({(int)response.StatusCode})";
|
||||
}
|
||||
|
||||
/// <summary>Returns the channel's reusable stream (TASK 5 design decision 2):
|
||||
/// lists existing streams first and reuses the one with cdn.isReusable=true,
|
||||
/// creating it with variable resolution/frame rate on first use. Binding to a
|
||||
|
||||
Reference in New Issue
Block a user