以下情境为教学假设,人物与数字不代表经核实的真实案例。
版税看起来只是一个百分比,实际却包含三个独立决定:按什么基数算、按什么单位收、有没有下限。基数决定分成是毛收入还是净收入,单位决定收入随销量还是随价格变化,下限决定销售不及预期时谁承担后果。三个决定组合起来,才是一份完整的版税条款。
Tidecast 的授权报价是保底 60,000 美元一年,再加 8% 净收入,期限 3 年,最低保证 180,000 美元。这组数字里,60,000 和 8% 不是简单的“取大”,而是两种完全不同的现金流:保底是固定的下限,分成是浮动的上限。这一节把两者拆开,算清楚在当前销量下谁付多少、保底对应多高的销量、以及阶梯费率在什么位置才开始起作用。
三种版税结构
版税结构常见的有三种:按净收入比例、按销量、按阶梯费率。它们的区别不在百分比高低,而在风险落在谁身上。
| 结构 | 计算基数 | 授权方的上行 | 被授权方的风险 | 管理成本 |
|---|---|---|---|---|
| 按净收入比例 | 扣除退款、平台费、支付费后的收入 | 随售价和销量一起涨 | 收入下滑时少付 | 低,按报表算 |
| 按销量 | 每份固定金额 | 只随销量涨,不随售价涨 | 降价促销时相对更痛 | 低,按数量算 |
| 阶梯费率 | 分档后的净收入 | 超过门槛后分成更高 | 增长越快,边际成本越高 | 中,要核对分档 |
按净收入比例最常用,因为它自动跟随实际到账的钱。Tidecast 的净收入 138,171 美元,是标价收入 191,904 美元扣掉退款 7,676 美元、平台分成 44,215 美元和支付费 1,842 美元之后的余额。8% 算在这个净额上,是 11,054 美元;如果算在标价收入上,是 15,352 美元,差了 4,298 美元。基数写错,百分比再精确也没有意义。
按销量适合单价稳定、渠道折扣少的产品。它把“卖了多少份”和“收了多少钱”分开:授权方拿到的是每份固定金额,被授权方做降价促销时,版税不会跟着降价。对授权方来说,这在下行周期更稳;对被授权方来说,这在上行周期更贵,因为涨价的好处全部留在自己手里。
阶梯费率是前两种的混合。它在低档给一个较低的比例,鼓励被授权方把销量做起来;超过门槛后提高比例,让授权方分享增长。门槛可以按年净收入、累计销量或单款产品设定。阶梯的关键不是档位数量,而是“按什么周期累计”。按年累计,被授权方可以在每年初重新从低档开始;按合同期累计,门槛只会被跨过一次。两种算法的现金流差别很大。
保底是一份下限,不是预付款
保底的常见写法是:每个授权年度,被授权方支付“保底金额”与“按净收入计算的版税”两者中的较大值。它的效果是给授权方一个下限,同时给被授权方一个固定成本。
| 年度版税 | 保底 | 被授权方实付 | 差额性质 |
|---|---|---|---|
| $11,054 | $60,000 | $60,000 | 保底高于分成,补足 $48,946 |
| $60,000 | $60,000 | $60,000 | 两者相等,按保底付 |
| $85,000 | $60,000 | $85,000 | 分成高于保底,按分成付 |
这张表就是保底的全部逻辑:分成低于保底时,被授权方补到保底;分成高于保底时,按分成付,保底不再额外收取。它不是“保底 + 分成”,而是“保底与分成取大”。如果合同写成“保底 + 分成”,那是另一种交易,价格和风险都要重算。
保底对现金流的影响,可以换一个角度看。对被授权方,保底是一笔固定支出:无论卖多少,60,000 美元都要付。对授权方,保底是一笔固定收入:无论卖多少,60,000 美元都能收到。固定支出加浮动分成,会让被授权方的利润在销量下滑时收缩得更快;固定收入加浮动上限,会让授权方的收入在销量爆发时分享得更少。
这也是保底谈判的核心:授权方要的是“最坏情况下也能收回多少”,被授权方要的是“最好情况下不用多付多少”。两边争的不是 8% 这个数字,而是 60,000 美元这个下限。下限越高,授权方的下行保护越强,被授权方的固定成本越高,交易越难谈成。
保底还有一种变体:可抵扣预付款。被授权方先付一笔钱,之后用应得版税逐期抵扣,抵完为止。案例写的是“保底 60,000 美元一年 + 8% 净收入,3 年,最低保证 180,000 美元”,更接近逐年取大的下限,而不是一次性预付款。两种结构的现金流完全不同:预付款是期初一次性到账,下限是每年结算时补足。读合同时要先分清是哪一种。
Tidecast 的 60,000 与 8%
把 Tidecast 的净收入 138,171 美元代入 8%:
8% 版税 = 138,171 × 8% = 11,053.68 美元 ≈ 11,054 美元
保底是 60,000 美元,高于 11,054 美元,所以被授权方当年实付 60,000 美元,补足差额:
补足额 = 60,000 − 11,054 = 48,946 美元
如果只看“8%”这个数字,会以为授权方一年只拿 11,054 美元;实际拿的是 60,000 美元。把实付除以净收入,得到有效费率:
有效费率 = 60,000 ÷ 138,171 = 43.4%
43.4% 不是版税率,而是保底在当前销量下的等效费率。它说明:保底越高、销量越低,有效费率越接近“保底 ÷ 净收入”;只有销量足够高,有效费率才会回落到 8%。
3 年期的账同样要按“取大”算。如果销量维持当前水平,每年版税 11,054 美元,3 年合计 33,162 美元;保底 3 年合计 180,000 美元,授权方多收 146,838 美元。如果销量增长到每年净收入 750,000 美元,8% 正好是 60,000 美元,保底与分成相等;再往上,分成开始超过保底,3 年总额随销量上升。
保底对应的最低销量门槛,可以按每份净得反推。Tidecast 年销 9,600 份,净收入 138,171 美元,每份净得:
每份净得 = 138,171 ÷ 9,600 = 14.39 美元 ≈ 1,439 美分
8% 的每份版税是 115 美分。要凑够 60,000 美元保底:
最低销量 = 60,000 ÷ 1.15 = 52,174 份
52,174 份是当前 9,600 份的 5.4 倍。换句话说,保底 60,000 美元隐含的假设是:被授权方能把销量做到当前水平的 5 倍以上,否则保底永远高于分成,授权方拿的一直是固定下限。这个门槛也可以用净收入表达:60,000 ÷ 8% = 750,000 美元净收入,是当前 138,171 美元的 5.4 倍,两种口径一致。
| 指标 | 当前 | 保底平衡点 | 倍数 |
|---|---|---|---|
| 年销量 | 9,600 份 | 52,174 份 | 5.4× |
| 净收入 | $138,171 | $750,000 | 5.4× |
| 8% 版税 | $11,054 | $60,000 | 5.4× |
| 有效费率 | 43.4% | 8.0% | — |
这张表把“保底”翻译成了被授权方必须达到的销售目标。它不是精确预测,而是一条谈判线:如果被授权方自己都不相信能卖到 5.4 倍,60,000 美元的保底就是一份定价过高的固定成本;如果它相信能卖到 10 倍,保底只是第一年的下限,后面的分成才是主要收入。
阶梯费率在什么位置起作用
阶梯费率的常见写法是:净收入低于某个门槛时按 8%,超过部分按 10%。门槛设在哪里,决定了阶梯是“增长分享”还是“变相涨价”。
| 年净收入 | 固定 8% | 阶梯 8%/10%(门槛 $750,000) | 保底应付 |
|---|---|---|---|
| $138,171 | $11,054 | $11,054 | $60,000 |
| $750,000 | $60,000 | $60,000 | $60,000 |
| $1,000,000 | $80,000 | $85,000 | $85,000 |
门槛设在 750,000 美元时,阶梯的第一个拐点正好是保底平衡点。低于这个点,阶梯和固定 8% 没有区别,保底仍然主导;高于这个点,阶梯才开始多收。门槛设得越低,授权方越早分享增长,被授权方的边际成本越早上升;门槛设得越高,阶梯越像一份“只有大幅增长才触发”的奖励。
阶梯还有一个容易忽略的细节:分档是按“超过门槛的部分”还是按“全部收入”适用高费率。前者是边际阶梯,后者是追溯阶梯。以上表为例,净收入 1,000,000 美元时,边际阶梯是 60,000 + 250,000 × 10% = 85,000 美元;追溯阶梯是 1,000,000 × 10% = 100,000 美元。两者差 15,000 美元。合同里只写“超过 750,000 部分按 10%”还不够,要写清是边际还是追溯。
把保底与分成写成代码
下面的 royalty.ts 把三种结构写成可复算的函数:royaltyOnNet 算净收入比例,royaltyPerUnit 算按销量,tieredRoyalty 算阶梯,settleGuarantee 算保底与分成的取大,minimumUnits 把保底反推成销量门槛。
// file: src/contract/royalty.ts
// tier: L1
// verify: node --test test/contract/royalty.test.ts
import { type Cents } from "../core/money.ts";
import { type Bps, applyRate, divide } from "../core/rate.ts";
import { type Result, fail, ok } from "../core/result.ts";
export type RoyaltyTier = {
upToCents: Cents | null;
rateBps: Bps;
};
export type GuaranteeSettlement = {
royaltyCents: Cents;
guaranteeCents: Cents;
payableCents: Cents;
shortfallCents: Cents;
effectiveRateBps: Bps;
};
export type UnitThreshold = {
royaltyPerUnitCents: Cents;
minimumUnits: number;
minimumNetRevenueCents: Cents;
};
function checkBps(value: Bps, label: string): string | null {
if (!Number.isInteger(value) || value < 0 || value > 10000) {
return `${label} must be between 0 and 10000 bps`;
}
return null;
}
function checkAmount(value: Cents, label: string): string | null {
if (!Number.isInteger(value) || value < 0) {
return `${label} must be a non-negative integer amount in cents`;
}
return null;
}
export function royaltyOnNet(
netRevenueCents: Cents,
rateBps: Bps,
): Result<Cents> {
const amountError = checkAmount(netRevenueCents, "net revenue");
if (amountError) {
return fail(amountError);
}
const rateError = checkBps(rateBps, "royalty rate");
if (rateError) {
return fail(rateError);
}
return ok(applyRate(netRevenueCents, rateBps));
}
export function royaltyPerUnit(
units: number,
ratePerUnitCents: Cents,
): Result<Cents> {
if (!Number.isInteger(units) || units < 0) {
return fail("units must be a non-negative integer");
}
const amountError = checkAmount(ratePerUnitCents, "per-unit royalty");
if (amountError) {
return fail(amountError);
}
return ok(units * ratePerUnitCents);
}
export function tieredRoyalty(
netRevenueCents: Cents,
tiers: RoyaltyTier[],
): Result<Cents> {
const amountError = checkAmount(netRevenueCents, "net revenue");
if (amountError) {
return fail(amountError);
}
if (tiers.length === 0) {
return fail("at least one tier is required");
}
let previous = 0;
let total = 0;
for (let index = 0; index < tiers.length; index += 1) {
const tier = tiers[index];
const rateError = checkBps(tier.rateBps, `tier ${index + 1} rate`);
if (rateError) {
return fail(rateError);
}
if (index < tiers.length - 1 && tier.upToCents === null) {
return fail("only the last tier may be open-ended");
}
const cap = tier.upToCents === null ? netRevenueCents : tier.upToCents;
if (!Number.isInteger(cap) || cap < previous) {
return fail(`tier ${index + 1} cap must not decrease`);
}
const band = Math.min(netRevenueCents, cap) - previous;
if (band > 0) {
total += applyRate(band, tier.rateBps);
}
previous = cap;
if (netRevenueCents <= cap) {
break;
}
}
return ok(total);
}
/**
* A minimum guarantee is a floor, not an advance: the licensee pays the
* larger of the guarantee and the earned royalty. The effective rate is
* measured against net revenue, so a guarantee can look like a very high
* royalty rate when sales are far below the guarantee.
*/
export function settleGuarantee(
netRevenueCents: Cents,
rateBps: Bps,
guaranteeCents: Cents,
): Result<GuaranteeSettlement> {
const royalty = royaltyOnNet(netRevenueCents, rateBps);
if (!royalty.ok) {
return royalty;
}
const amountError = checkAmount(guaranteeCents, "guarantee");
if (amountError) {
return fail(amountError);
}
const payableCents = Math.max(royalty.value, guaranteeCents);
const shortfallCents = Math.max(0, guaranteeCents - royalty.value);
return ok({
royaltyCents: royalty.value,
guaranteeCents,
payableCents,
shortfallCents,
effectiveRateBps:
netRevenueCents === 0 ? 0 : divide(payableCents, netRevenueCents),
});
}
/**
* Converts a guarantee into the sales volume that would make the earned
* royalty equal the guarantee. The per-unit rate is rounded to cents first,
* so the unit threshold is the number the licensee can actually count.
*/
export function minimumUnits(
guaranteeCents: Cents,
netPerUnitCents: Cents,
rateBps: Bps,
): Result<UnitThreshold> {
const guaranteeError = checkAmount(guaranteeCents, "guarantee");
if (guaranteeError) {
return fail(guaranteeError);
}
const unitError = checkAmount(netPerUnitCents, "net per unit");
if (unitError) {
return fail(unitError);
}
const rateError = checkBps(rateBps, "royalty rate");
if (rateError) {
return fail(rateError);
}
if (rateBps === 0) {
return fail("royalty rate must be positive to compute a threshold");
}
const royaltyPerUnitCents = applyRate(netPerUnitCents, rateBps);
if (royaltyPerUnitCents === 0) {
return fail("per-unit royalty rounds to zero");
}
return ok({
royaltyPerUnitCents,
minimumUnits: Math.ceil(guaranteeCents / royaltyPerUnitCents),
minimumNetRevenueCents: Math.ceil((guaranteeCents * 10000) / rateBps),
});
}
把 Tidecast 的数字代入:净收入 13,817,100 美分、费率 800 基点,royaltyOnNet 返回 1,105,368 美分,即 11,053.68 美元;settleGuarantee 返回实付 6,000,000 美分、补足 4,894,632 美分、有效费率 4,342 基点,即 43.4%。把保底 6,000,000 美分、每份净得 1,439 美分、费率 800 基点代入 minimumUnits,得到每份版税 115 美分、最低销量 52,174 份、最低净收入 75,000,000 美分。
代码里有三个刻意的限制。第一,金额用整数美分,费率用基点,避免 0.08 和 2.5 在连续计算里漂移。第二,settleGuarantee 返回的是“取大”后的实付,不是“保底 + 分成”;如果合同真是叠加结构,要另写函数,不能复用这个结果。第三,minimumUnits 先把每份版税取整到美分,再算销量门槛;用未取整的每份版税会得到 52,109 份,差 65 份,这个差异来自取整口径,不是计算错误。
保底和分成确定之后,剩下的是执行:被授权方报的净收入是否真实、版税是否按约支付、超范围使用有没有被发现。这些问题的答案不在报价表里,而在审计权和终止条款里,这是 8.3 节的内容。
小结
- 版税有三个独立决定:基数、单位、下限;百分比只是其中最显眼的一个。
- 按净收入比例跟随实际到账,按销量跟随数量,阶梯费率在门槛以上分享增长;三者风险分配不同。
- 保底是“保底与分成取大”,不是“保底 + 分成”;分成低于保底时补足,高于保底时按分成付。
- Tidecast 当前净收入 138,171 美元,8% 版税 11,054 美元,低于 60,000 美元保底,实付 60,000 美元,补足 48,946 美元,有效费率 43.4%。
- 保底平衡点是净收入 750,000 美元或销量 52,174 份,都是当前水平的 5.4 倍。
- 3 年保底 180,000 美元;按当前销量,3 年版税只有 33,162 美元,保底比分成多 146,838 美元。
- 阶梯费率要写清门槛、累计周期和边际/追溯口径;门槛设在保底平衡点时,阶梯在拐点之后才起作用。
阅读导航:上一节:8.1 授权类型:独占、排他、普通 · 下一节:8.3 授权审计与终止 。
常见错误与边界
- 把保底当成预付款。 逐年取大的保底是下限,不是期初一次性到账;预付款可以抵扣未来版税,两者的现金流完全不同。
- 把“保底 + 分成”当成“取大”。 叠加结构下,被授权方要付 60,000 + 11,054 = 71,054 美元;取大结构只付 60,000 美元,差 11,054 美元。
- 用标价收入算 8%。 Tidecast 的标价收入 191,904 美元,8% 是 15,352 美元;净收入 138,171 美元,8% 是 11,054 美元,基数不同,差 4,298 美元。
- 忽略保底的有效费率。 当前销量下有效费率是 43.4%,不是 8%;只看 8% 会低估被授权方的固定成本。
- 把 3 年保底当成 3 年分成。 180,000 美元是最低保证,不是按 8% 算出的预期版税;按当前销量,3 年版税只有 33,162 美元。
- 不反推销量门槛。 保底 60,000 美元对应 52,174 份或 750,000 美元净收入;不把这个数字摆上桌,谈判就只是在猜。
- 阶梯费率不写累计周期。 按年累计和按合同期累计,门槛被跨过的次数不同,3 年总额可能差出一整档。
- 把边际阶梯写成追溯阶梯。 净收入 1,000,000 美元时,两者差 15,000 美元;合同里只写“超过部分按 10%”不够,要写清计算方式。
- 用每份版税反推时忽略取整。 每份 115 美分得到 52,174 份,未取整得到 52,109 份;差 65 份,来自取整口径。
- 只算授权方收入,不算被授权方现金流。 保底是被授权方的固定支出,销量下滑时利润收缩更快;只从授权方角度看,会低估交易对手的违约概率。
本节的边界是“单一产品、单一渠道、按年结算”的静态模型。它假设净收入口径稳定、销量均匀发生、保底按年取大,不含跨年结转、不含预付款抵扣、不含汇率和税务预提。它足够回答“保底和分成怎么算”,但不足以回答“被授权方少报收入怎么办”。后者需要审计权和终止条款,这正是 8.3 节的内容。本节不构成法律意见,具体版税条款请由律师审阅。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。