-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathAudioSegment.cs
More file actions
192 lines (171 loc) · 7.21 KB
/
AudioSegment.cs
File metadata and controls
192 lines (171 loc) · 7.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
using JyDraft.meta;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using static JyDraft.TimeUtil;
namespace JyDraft
{
public class AudioFade
{
public string FadeId { get; }
public int InDuration { get; }
public int OutDuration { get; }
public AudioFade(int inDuration, int outDuration)
{
FadeId = Guid.NewGuid().ToString();
InDuration = inDuration;
OutDuration = outDuration;
}
public Dictionary<string, object> ExportJson()
{
return new Dictionary<string, object>
{
{ "id", FadeId },
{ "fade_in_duration", InDuration },
{ "fade_out_duration", OutDuration },
{ "fade_type", 0 },
{ "type", "audio_fade" }
};
}
}
public class AudioEffect
{
public string Name { get; }
public string EffectId { get; }
public string ResourceId { get; }
public string CategoryId { get; }
public string CategoryName { get; }
public List<EffectParamInstance> AudioAdjustParams { get; }
public AudioEffect(EffectMeta effectMeta, List<float?> parameters = null)
{
// effectMeta 类型需根据实际情况实现,如 AudioSceneEffectType, ToneEffectType, SpeechToSongType
var category = AudioEffectCategoryResolver.GetCategory(effectMeta);
switch (category)
{
case AudioEffectCategory.Tone:
CategoryId = "tone";
CategoryName = "音色";
Name = effectMeta.Name;
ResourceId = effectMeta.ResourceId;
AudioAdjustParams = effectMeta.ParseParams(parameters);
break;
case AudioEffectCategory.Audio:
CategoryId = "sound_effect";
CategoryName = "场景音";
Name = effectMeta.Name;
ResourceId = effectMeta.ResourceId;
AudioAdjustParams = effectMeta.ParseParams(parameters);
break;
case AudioEffectCategory.Song:
CategoryId = "speech_to_song";
CategoryName = "声音成曲";
Name = effectMeta.Name;
ResourceId = effectMeta.ResourceId;
AudioAdjustParams = effectMeta.ParseParams(parameters);
break;
default:
throw new InvalidOperationException("不支持的元数据类型。");
}
EffectId = Guid.NewGuid().ToString();
}
public Dictionary<string, object> ExportJson()
{
return new Dictionary<string, object>
{
{ "audio_adjust_params", AudioAdjustParams.Select(p => p.ExportJson()).ToList() },
{ "category_id", CategoryId },
{ "category_name", CategoryName },
{ "id", EffectId },
{ "is_ugc", false },
{ "name", Name },
{ "production_path", "" },
{ "resource_id", ResourceId },
{ "speaker_id", "" },
{ "sub_type", 1 },
{ "time_range", new Dictionary<string, int> { {"duration", 0}, {"start", 0} } },
{ "type", "audio_effect" }
};
}
}
public class AudioSegment : MediaSegment
{
public AudioMaterial MaterialInstance { get; }
public AudioFade Fade { get; private set; }
public List<AudioEffect> Effects { get; }
// public List<string> ExtraMaterialRefs { get; } // 你可以在基类实现
public AudioSegment(AudioMaterial material, Timerange targetTimerange, Timerange sourceTimerange = null, float? speed = null, float volume = 1.0f)
: base(material.MaterialId, null, null, 1.0f, volume)
{
// 速度、时间区间的推导逻辑
if (sourceTimerange != null && speed.HasValue)
{
targetTimerange = new Timerange(targetTimerange.Start, (int)Math.Round(sourceTimerange.Duration / speed.Value));
}
else if (sourceTimerange != null)
{
speed = sourceTimerange.Duration / (float)targetTimerange.Duration;
}
else
{
speed = speed ?? 1.0f;
sourceTimerange = new Timerange(0, (int)Math.Round(targetTimerange.Duration * speed.Value));
}
if (sourceTimerange.End > material.Duration)
throw new ArgumentException($"截取的素材时间范围 {sourceTimerange} 超出了素材时长({material.Duration})");
// 初始化父类
base.SourceTimerange = sourceTimerange;
base.TargetTimerange = targetTimerange;
base.Speed.Value = speed.Value;
MaterialInstance = material; // 假设实现了 Clone
Effects = new List<AudioEffect>();
}
public AudioSegment AddEffect(EffectMeta effectType, List<float?> parameters = null)
{
// effectType 类型需根据实际情况实现
var effectInst = new AudioEffect(effectType, parameters);
if (Effects.Any(e => e.CategoryId == effectInst.CategoryId))
throw new ArgumentException($"当前音频片段已经有此类型 ({effectInst.CategoryName}) 的音效了");
Effects.Add(effectInst);
ExtraMaterialRefs.Add(effectInst.EffectId);
return this;
}
public AudioSegment AddFade(object inDuration, object outDuration)
{
if (Fade != null)
throw new ArgumentException("当前片段已存在淡入淡出效果");
int ParseDuration(object duration)
{
if (duration is int i) return i;
if (duration is string s) return TimeUtil.Tim(s); // 假设有 TimUtil.Tim(string) 方法
throw new ArgumentException("无效的时长参数");
}
Fade = new AudioFade(ParseDuration(inDuration), ParseDuration(outDuration));
ExtraMaterialRefs.Add(Fade.FadeId);
return this;
}
public AudioSegment AddKeyframe(int timeOffset, float volume)
{
var property = KeyframeProperty.Volume;
var kfList = CommonKeyframes.FirstOrDefault(k => k.Property == property);
if (kfList != null)
{
kfList.AddKeyframe(timeOffset, volume);
return this;
}
kfList = new KeyframeList(property);
kfList.AddKeyframe(timeOffset, volume);
CommonKeyframes.Add(kfList);
return this;
}
public override Dictionary<string, object> ExportJson()
{
var jsonDict = base.ExportJson();
jsonDict["clip"] = null;
jsonDict["hdr_settings"] = null;
return jsonDict;
}
}
}