@jjlmoya/utils-audiovisual 1.18.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/package.json +1 -1
  2. package/src/category/i18n/de.ts +1 -1
  3. package/src/category/i18n/fr.ts +1 -1
  4. package/src/category/i18n/ru.ts +1 -1
  5. package/src/category/index.ts +2 -0
  6. package/src/entries.ts +4 -1
  7. package/src/index.ts +1 -0
  8. package/src/tests/diacritics_density.test.ts +118 -0
  9. package/src/tests/inverted_punctuation.test.ts +84 -0
  10. package/src/tests/locale_completeness.test.ts +2 -2
  11. package/src/tests/no_en_dash.test.ts +70 -0
  12. package/src/tests/script_density.test.ts +94 -0
  13. package/src/tests/tool_validation.test.ts +2 -2
  14. package/src/tool/chromaticLens/i18n/de.ts +6 -6
  15. package/src/tool/chromaticLens/i18n/fr.ts +3 -3
  16. package/src/tool/chromaticLens/i18n/pl.ts +1 -1
  17. package/src/tool/chromaticLens/i18n/ru.ts +10 -10
  18. package/src/tool/chromaticLens/i18n/zh.ts +2 -2
  19. package/src/tool/collageMaker/i18n/de.ts +6 -6
  20. package/src/tool/collageMaker/i18n/fr.ts +4 -4
  21. package/src/tool/collageMaker/i18n/pl.ts +5 -5
  22. package/src/tool/collageMaker/i18n/ru.ts +12 -12
  23. package/src/tool/collageMaker/i18n/sv.ts +3 -3
  24. package/src/tool/collageMaker/i18n/zh.ts +1 -1
  25. package/src/tool/depthOfFieldCalculator/i18n/de.ts +3 -3
  26. package/src/tool/depthOfFieldCalculator/i18n/en.ts +7 -7
  27. package/src/tool/depthOfFieldCalculator/i18n/es.ts +2 -2
  28. package/src/tool/depthOfFieldCalculator/i18n/fr.ts +6 -6
  29. package/src/tool/depthOfFieldCalculator/i18n/id.ts +2 -2
  30. package/src/tool/depthOfFieldCalculator/i18n/it.ts +2 -2
  31. package/src/tool/depthOfFieldCalculator/i18n/ja.ts +1 -1
  32. package/src/tool/depthOfFieldCalculator/i18n/ko.ts +1 -1
  33. package/src/tool/depthOfFieldCalculator/i18n/nl.ts +2 -2
  34. package/src/tool/depthOfFieldCalculator/i18n/pl.ts +2 -2
  35. package/src/tool/depthOfFieldCalculator/i18n/pt.ts +2 -2
  36. package/src/tool/depthOfFieldCalculator/i18n/ru.ts +6 -6
  37. package/src/tool/depthOfFieldCalculator/i18n/sv.ts +2 -2
  38. package/src/tool/depthOfFieldCalculator/i18n/tr.ts +1 -1
  39. package/src/tool/depthOfFieldCalculator/i18n/zh.ts +3 -3
  40. package/src/tool/exifCleaner/i18n/de.ts +8 -8
  41. package/src/tool/exifCleaner/i18n/fr.ts +11 -11
  42. package/src/tool/exifCleaner/i18n/pl.ts +6 -6
  43. package/src/tool/exifCleaner/i18n/ru.ts +14 -14
  44. package/src/tool/exifCleaner/i18n/zh.ts +3 -3
  45. package/src/tool/imageCompressor/i18n/de.ts +16 -16
  46. package/src/tool/imageCompressor/i18n/fr.ts +8 -8
  47. package/src/tool/imageCompressor/i18n/pl.ts +1 -1
  48. package/src/tool/imageCompressor/i18n/ru.ts +9 -9
  49. package/src/tool/imageCompressor/i18n/zh.ts +1 -1
  50. package/src/tool/printQualityCalculator/component.astro +118 -110
  51. package/src/tool/printQualityCalculator/i18n/de.ts +5 -5
  52. package/src/tool/printQualityCalculator/i18n/fr.ts +11 -11
  53. package/src/tool/printQualityCalculator/i18n/pl.ts +4 -4
  54. package/src/tool/printQualityCalculator/i18n/ru.ts +11 -11
  55. package/src/tool/printQualityCalculator/i18n/zh.ts +4 -4
  56. package/src/tool/printQualityCalculator/print-quality-calculator-pixels-to-cm-dpi.css +193 -40
  57. package/src/tool/privacyBlur/i18n/de.ts +5 -5
  58. package/src/tool/privacyBlur/i18n/fr.ts +9 -9
  59. package/src/tool/privacyBlur/i18n/ru.ts +6 -6
  60. package/src/tool/subtitleSync/i18n/de.ts +1 -1
  61. package/src/tool/subtitleSync/i18n/fr.ts +9 -9
  62. package/src/tool/subtitleSync/i18n/ru.ts +6 -6
  63. package/src/tool/subtitleSync/i18n/sv.ts +4 -4
  64. package/src/tool/timelapseCalculator/i18n/fr.ts +6 -6
  65. package/src/tool/timelapseCalculator/i18n/ru.ts +3 -3
  66. package/src/tool/timelapseCalculator/i18n/zh.ts +4 -4
  67. package/src/tool/tvDistance/i18n/fr.ts +2 -2
  68. package/src/tool/tvDistance/i18n/ru.ts +9 -9
  69. package/src/tool/tvDistance/i18n/zh.ts +4 -4
  70. package/src/tool/videoFrameExtractor/i18n/fr.ts +8 -8
  71. package/src/tool/videoFrameExtractor/i18n/ru.ts +2 -2
  72. package/src/tool/videoMerger/bibliography.astro +17 -0
  73. package/src/tool/videoMerger/bibliography.ts +16 -0
  74. package/src/tool/videoMerger/component.astro +400 -0
  75. package/src/tool/videoMerger/entry.ts +51 -0
  76. package/src/tool/videoMerger/i18n/de.ts +205 -0
  77. package/src/tool/videoMerger/i18n/en.ts +205 -0
  78. package/src/tool/videoMerger/i18n/es.ts +205 -0
  79. package/src/tool/videoMerger/i18n/fr.ts +205 -0
  80. package/src/tool/videoMerger/i18n/id.ts +205 -0
  81. package/src/tool/videoMerger/i18n/it.ts +205 -0
  82. package/src/tool/videoMerger/i18n/ja.ts +205 -0
  83. package/src/tool/videoMerger/i18n/ko.ts +205 -0
  84. package/src/tool/videoMerger/i18n/nl.ts +205 -0
  85. package/src/tool/videoMerger/i18n/pl.ts +205 -0
  86. package/src/tool/videoMerger/i18n/pt.ts +205 -0
  87. package/src/tool/videoMerger/i18n/ru.ts +205 -0
  88. package/src/tool/videoMerger/i18n/sv.ts +205 -0
  89. package/src/tool/videoMerger/i18n/tr.ts +205 -0
  90. package/src/tool/videoMerger/i18n/zh.ts +205 -0
  91. package/src/tool/videoMerger/index.ts +11 -0
  92. package/src/tool/videoMerger/logic.ts +263 -0
  93. package/src/tool/videoMerger/online-video-merger.css +440 -0
  94. package/src/tool/videoMerger/seo.astro +15 -0
  95. package/src/tools.ts +2 -0
@@ -67,7 +67,7 @@ const seo: SubtitleSyncLocaleContent['seo'] = [
67
67
  items: [
68
68
  'Omedelbar korrigering av osynk mellan ljud och undertext',
69
69
  'Stöd för SRT-standardfiler (SubRip)',
70
- '100 % lokal bearbetning maximal integritet',
70
+ '100 % lokal bearbetning - maximal integritet',
71
71
  'Ingen installation, inget abonnemang, helt gratis'
72
72
  ]
73
73
  },
@@ -137,15 +137,15 @@ const seo: SubtitleSyncLocaleContent['seo'] = [
137
137
 
138
138
  { type: 'proscons', items: [
139
139
  {
140
- pro: 'Extrem hastighet bearbetar stora filer på millisekunder',
140
+ pro: 'Extrem hastighet - bearbetar stora filer på millisekunder',
141
141
  con: 'Justerar endast fast förskjutning, inte progressiva'
142
142
  },
143
143
  {
144
- pro: 'Total integritet innehållet lämnar aldrig webbläsaren',
144
+ pro: 'Total integritet - innehållet lämnar aldrig webbläsaren',
145
145
  con: 'Kräver modern webbläsare med JavaScript aktiverat'
146
146
  },
147
147
  {
148
- pro: 'Universellt format fungerar med alla standard SRT',
148
+ pro: 'Universellt format - fungerar med alla standard SRT',
149
149
  con: 'Stöder inte andra format (ASS, VTT, SCC, etc.)'
150
150
  },
151
151
  {
@@ -3,7 +3,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
3
3
  import type { TimelapseUI, TimelapseLocaleContent } from '../index';
4
4
 
5
5
  const slug = 'calculatrice-timelapse-hyperlapse-intervalles-parfaits';
6
- const title = 'Calculatrice de Timelapse et Hyperlapse : Intervalles Parfaits';
6
+ const title = 'Calculatrice de Timelapse et Hyperlapse: Intervalles Parfaits';
7
7
  const description = 'Calculez l\'intervalle exact entre les photos, la durée totale et le stockage pour vos timelapses. Outil essentiel pour les photographes.';
8
8
 
9
9
  const ui: TimelapseUI = {
@@ -47,11 +47,11 @@ const faq: TimelapseLocaleContent['faq'] = [
47
47
  const howTo: TimelapseLocaleContent['howTo'] = [
48
48
  {
49
49
  name: "Définir la durée de la vidéo finale",
50
- text: "Indiquez combien de secondes ou de minutes vous souhaitez que la vidéo résultante dure (ex : 10 secondes pour Instagram).",
50
+ text: "Indiquez combien de secondes ou de minutes vous souhaitez que la vidéo résultante dure (ex: 10 secondes pour Instagram).",
51
51
  },
52
52
  {
53
53
  name: "Sélectionner les FPS de sortie",
54
- text: "Choisissez la fluidité de la vidéo : 24 (cinéma), 30 (web) ou 60 (ralenti fluide).",
54
+ text: "Choisissez la fluidité de la vidéo: 24 (cinéma), 30 (web) ou 60 (ralenti fluide).",
55
55
  },
56
56
  {
57
57
  name: "Ajuster l'intervalle de capture",
@@ -65,7 +65,7 @@ const howTo: TimelapseLocaleContent['howTo'] = [
65
65
 
66
66
  const seo: TimelapseLocaleContent['seo'] = [
67
67
  { type: 'title', text: 'Guide Ultime des Intervalles Timelapse et Hyperlapse', level: 2 },
68
- { type: 'paragraph', html: 'La différence entre une vidéo accélérée amateur et un <strong>timelapse cinématographique</strong> réside mathématiquement dans un seul facteur : <strong>l\'intervalle</strong>. Cette calculatrice élimine les devinettes, vous permettant de planifier avec précision la capture de levers de soleil, du trafic urbain ou de la Voie lactée.' },
68
+ { type: 'paragraph', html: 'La différence entre une vidéo accélérée amateur et un <strong>timelapse cinématographique</strong> réside mathématiquement dans un seul facteur: <strong>l\'intervalle</strong>. Cette calculatrice élimine les devinettes, vous permettant de planifier avec précision la capture de levers de soleil, du trafic urbain ou de la Voie lactée.' },
69
69
 
70
70
  { type: 'title', text: 'Tableau des Intervalles Recommandés (Aide mémoire)', level: 3 },
71
71
  { type: 'paragraph', html: 'Utilisez ce tableau de référence rapide pour régler votre intervallomètre en fonction du sujet.' },
@@ -91,7 +91,7 @@ const seo: TimelapseLocaleContent['seo'] = [
91
91
  '<strong>Photographiez en RAW :</strong> Essentiel pour corriger l\'exposition en post-production sans détruire l\'image.'
92
92
  ]},
93
93
 
94
- { type: 'diagnostic', variant: 'success', title: 'Technique Avancée : Le "Saint Graal"', icon: 'mdi:crown', badge: 'Technique Pro', html: 'On appelle "Saint Graal" la transition fluide du jour à la nuit (ou vice-versa). C\'est le défi technique le plus difficile car la lumière change radicalement.' },
94
+ { type: 'diagnostic', variant: 'success', title: 'Technique Avancée: Le "Saint Graal"', icon: 'mdi:crown', badge: 'Technique Pro', html: 'On appelle "Saint Graal" la transition fluide du jour à la nuit (ou vice-versa). C\'est le défi technique le plus difficile car la lumière change radicalement.' },
95
95
 
96
96
  { type: 'stats', columns: 3, items: [
97
97
  { label: 'Bulb Ramping', value: 'Exposition Graduelle', icon: 'mdi:brightness-6' },
@@ -99,7 +99,7 @@ const seo: TimelapseLocaleContent['seo'] = [
99
99
  { label: 'Stratégie', value: 'Intervalle Nocturne', icon: 'mdi:weather-night' }
100
100
  ]},
101
101
 
102
- { type: 'title', text: 'Conclusion : Le Zen de la Mécanique Simple', level: 3 },
102
+ { type: 'title', text: 'Conclusion: Le Zen de la Mécanique Simple', level: 3 },
103
103
  { type: 'paragraph', html: 'Maîtriser votre timelapse commence par comprendre les mathématiques de votre intervallomètre. Ne laissez pas un intervalle mal choisi gâcher votre session.' }
104
104
  ];
105
105
 
@@ -28,7 +28,7 @@ const ui: TimelapseUI = {
28
28
  const faq: TimelapseLocaleContent['faq'] = [
29
29
  {
30
30
  question: "Как выбрать правильный интервал для моего таймлапса?",
31
- answer: "Это зависит от скорости движения, которое вы снимаете. Для быстро движущихся облаков используйте 2-3 секунды. Для движения солнца или звезд 15-30 секунд. Для роста растений или строительства 5-15 минут.",
31
+ answer: "Это зависит от скорости движения, которое вы снимаете. Для быстро движущихся облаков используйте 2-3 секунды. Для движения солнца или звезд - 15-30 секунд. Для роста растений или строительства - 5-15 минут.",
32
32
  },
33
33
  {
34
34
  question: "Сколько фотографий мне нужно для минутного видео?",
@@ -80,11 +80,11 @@ const seo: TimelapseLocaleContent['seo'] = [
80
80
  { type: 'tip', title: 'Заметка для астрофото', html: 'Интервал обычно диктуется временем экспозиции (правило 500) + 1 или 2 секунды буфера для записи на карту.' },
81
81
 
82
82
  { type: 'title', text: 'Правило 180° (Motion Blur)', level: 3 },
83
- { type: 'paragraph', html: 'Частая ошибка в таймлапсе получение "дерганого" видео. Для плавного киношного вида вам нужно <strong>размытие движения (motion blur)</strong>.' },
83
+ { type: 'paragraph', html: 'Частая ошибка в таймлапсе - получение "дерганого" видео. Для плавного киношного вида вам нужно <strong>размытие движения (motion blur)</strong>.' },
84
84
  { type: 'card', title: 'Правило', icon: 'mdi:information', html: 'Ваша выдержка должна составлять половину от интервала. <br /><br /> <em>Пример:</em> Если вы снимаете каждые <strong>4 секунды</strong>, экспозиция должна быть <strong>2 секунды</strong>.' },
85
85
 
86
86
  { type: 'title', text: 'Мерцание (Flicker) и ручная диафрагма', level: 3 },
87
- { type: 'paragraph', html: '"Flicker" это раздражающее мерцание, вызванное микроколебаниями в раскрытии диафрагмы между снимками.' },
87
+ { type: 'paragraph', html: '"Flicker" - это раздражающее мерцание, вызванное микроколебаниями в раскрытии диафрагмы между снимками.' },
88
88
  { type: 'list', items: [
89
89
  '<strong>Lens Twist:</strong> Приоткройте замок объектива на зеркалках, чтобы прервать электронную связь и зафиксировать диафрагму механически.',
90
90
  '<strong>Все в ручном режиме:</strong> ISO, баланс белого и фокус должны быть фиксированы.',
@@ -35,7 +35,7 @@ const faq: TimelapseLocaleContent['faq'] = [
35
35
  answer: "标准视频通常为每秒 24 或 30 帧 (fps)。对于一部 24fps 的一分钟视频,您恰好需要 1440 张照片(60 秒 * 24 张/秒)。",
36
36
  },
37
37
  {
38
- question: "什么是“闪烁”(Flicker) 以及如何避免?",
38
+ question: "什么是\"闪烁\"(Flicker) 以及如何避免?",
39
39
  answer: "这是由于照片之间微小的曝光差异导致的令人不快的闪烁感。要避免它,请始终使用手动模式 (M)、固定白平衡,并优先使用带有手动光圈环的镜头。",
40
40
  },
41
41
  {
@@ -80,18 +80,18 @@ const seo: TimelapseLocaleContent['seo'] = [
80
80
  { type: 'tip', title: '天文拍摄注記', html: '拍摄间隔通常受限于捕捉光线所需的曝光时间(500 法则) + 1 或 2 秒的存储写入缓冲时间。' },
81
81
 
82
82
  { type: 'title', text: '180° 快门法则(动态模糊)', level: 3 },
83
- { type: 'paragraph', html: '延时摄影中一个常见的错误是视频看起来“顿挫”或有频闪感。为了获得流畅的电影感,您需要 <strong>动态模糊 (Motion Blur)</strong>。' },
83
+ { type: 'paragraph', html: '延时摄影中一个常见的错误是视频看起来\"顿挫\"或有频闪感。为了获得流畅的电影感,您需要 <strong>动态模糊 (Motion Blur)</strong>。' },
84
84
  { type: 'card', title: '核心法则', icon: 'mdi:information', html: '您的快门速度应该是拍摄间隔的一半。<br /><br /> <em>例如:</em>如果您每隔 <strong>4 秒</strong> 拍摄一次,您的曝光时间应为 <strong>2 秒</strong>。' },
85
85
 
86
86
  { type: 'title', text: '闪烁 (Flicker) 与手动光圈', level: 3 },
87
- { type: 'paragraph', html: '“闪烁”是由于每次拍摄之间光圈叶片收缩的微小差异导致的图像亮度抖动。' },
87
+ { type: 'paragraph', html: '\"闪烁\"是由于每次拍摄之间光圈叶片收缩的微小差异导致的图像亮度抖动。' },
88
88
  { type: 'list', items: [
89
89
  '<strong>镜头微松法 (Lens Twist):</strong> 在单反相机上稍微拧松镜头以断开电子触点,使光圈机械固定。',
90
90
  '<strong>全手动设置:</strong> ISO、白平衡和对焦必须固定。切勿使用自动模式。',
91
91
  '<strong>通过 RAW 拍摄:</strong> 这对于在后期修正曝光和色彩而又不破坏画质至关重要。'
92
92
  ]},
93
93
 
94
- { type: 'diagnostic', variant: 'success', title: '进阶技术:日夜转换 (The "Holy Grail")', icon: 'mdi:crown', badge: '专家技法', html: '“圣杯拍摄”是指昼夜之间(或反之)的平滑过渡。这是难度最高的技术挑战之一。' },
94
+ { type: 'diagnostic', variant: 'success', title: '进阶技术:日夜转换 (The "Holy Grail")', icon: 'mdi:crown', badge: '专家技法', html: '\"圣杯拍摄\"是指昼夜之间(或反之)的平滑过渡。这是难度最高的技术挑战之一。' },
95
95
 
96
96
  { type: 'stats', columns: 3, items: [
97
97
  { label: 'Bulb Ramping', value: '渐变曝光', icon: 'mdi:brightness-6' },
@@ -67,7 +67,7 @@ const seo: TvDistanceLocaleContent['seo'] = [
67
67
  'Évitez la fatigue oculaire et maximisez l\'immersion'
68
68
  ]
69
69
  },
70
- { type: 'title', text: 'Science de l\'Immersion : Distance TV Optimale', level: 2 },
70
+ { type: 'title', text: 'Science de l\'Immersion: Distance TV Optimale', level: 2 },
71
71
  { type: 'paragraph', html: 'Il ne s\'agit pas seulement de confort, mais de physiologie visuelle humaine. L\'œil a une limite d\'acuité de résolution ; si vous êtes trop loin d\'un écran 4K, vous gaspillez des pixels que votre vision ne peut exploiter.' },
72
72
 
73
73
  { type: 'stats', items: [
@@ -76,7 +76,7 @@ const seo: TvDistanceLocaleContent['seo'] = [
76
76
  { value: 'Zéro', label: 'Fatigue Visuelle', icon: 'mdi:heart-pulse' }
77
77
  ], columns: 3 },
78
78
 
79
- { type: 'title', text: 'Deux Normes Professionnelles : THX vs SMPTE', level: 3 },
79
+ { type: 'title', text: 'Deux Normes Professionnelles: THX vs SMPTE', level: 3 },
80
80
  { type: 'paragraph', html: 'Il existe deux autorités principales dans l\'industrie audiovisuelle qui définissent comment optimiser votre expérience :' },
81
81
  { type: 'comparative', items: [
82
82
  {
@@ -25,7 +25,7 @@ const ui: TvDistanceUI = {
25
25
  const faq: TvDistanceLocaleContent['faq'] = [
26
26
  {
27
27
  question: "Почему разрешение важно при расчете расстояния?",
28
- answer: "При более высоком разрешении (например, 4K или 8K) пиксели меньше. Это позволяет сидеть ближе без ощущения «зернистости», что увеличивает эффект присутствия.",
28
+ answer: "При более высоком разрешении (например, 4K или 8K) пиксели меньше. Это позволяет сидеть ближе без ощущения \"зернистости\", что увеличивает эффект присутствия.",
29
29
  },
30
30
  {
31
31
  question: "Что такое угол обзора 40 градусов?",
@@ -52,7 +52,7 @@ const howTo: TvDistanceLocaleContent['howTo'] = [
52
52
  },
53
53
  {
54
54
  name: "Настройте положение дивана",
55
- text: "Разместите место для сидения в зоне «Оптимальное расстояние» для максимального погружения.",
55
+ text: "Разместите место для сидения в зоне \"Оптимальное расстояние\" для максимального погружения.",
56
56
  },
57
57
  ];
58
58
 
@@ -68,7 +68,7 @@ const seo: TvDistanceLocaleContent['seo'] = [
68
68
  ]
69
69
  },
70
70
  { type: 'title', text: 'Наука погружения: Оптимальное расстояние до ТВ', level: 2 },
71
- { type: 'paragraph', html: 'Дело не только в комфорте, но и в физиологии человеческого зрения. Если сидеть слишком далеко от 4K экрана, вы переплачиваете за пиксели, которые ваше зрение не может оценить. А если слишком близко это вызывает усталость глаз.' },
71
+ { type: 'paragraph', html: 'Дело не только в комфорте, но и в физиологии человеческого зрения. Если сидеть слишком далеко от 4K экрана, вы переплачиваете за пиксели, которые ваше зрение не может оценить. А если слишком близко - это вызывает усталость глаз.' },
72
72
 
73
73
  { type: 'stats', items: [
74
74
  { value: '40°', label: 'Идеальный угол THX', icon: 'mdi:eye' },
@@ -81,7 +81,7 @@ const seo: TvDistanceLocaleContent['seo'] = [
81
81
  { type: 'comparative', items: [
82
82
  {
83
83
  title: 'Стандарт THX',
84
- description: 'Угол обзора 40° Больше погружения',
84
+ description: 'Угол обзора 40° - Больше погружения',
85
85
  icon: 'mdi:filmstrip',
86
86
  points: [
87
87
  'Экран занимает большую часть периферийного зрения',
@@ -93,7 +93,7 @@ const seo: TvDistanceLocaleContent['seo'] = [
93
93
  },
94
94
  {
95
95
  title: 'Стандарт SMPTE',
96
- description: 'Угол обзора 30° Спокойнее',
96
+ description: 'Угол обзора 30° - Спокойнее',
97
97
  icon: 'mdi:television',
98
98
  points: [
99
99
  'Более комфортное расстояние для сидения',
@@ -113,9 +113,9 @@ const seo: TvDistanceLocaleContent['seo'] = [
113
113
 
114
114
  { type: 'paragraph', html: 'Как видите, высокое разрешение позволяет сидеть ближе. 4K ТВ можно оценить уже с 1.2 метра, тогда как 1080p требует минимум 2 метра.' },
115
115
 
116
- { type: 'card', title: 'Предел остроты зрения человека', html: 'Человеческий глаз имеет предел разрешения. На определенном расстоянии вы не отличите детали, даже если экран 8K. Наши расчеты помещают вас точно в «оптимальную зону».' },
116
+ { type: 'card', title: 'Предел остроты зрения человека', html: 'Человеческий глаз имеет предел разрешения. На определенном расстоянии вы не отличите детали, даже если экран 8K. Наши расчеты помещают вас точно в \"оптимальную зону\".' },
117
117
 
118
- { type: 'diagnostic', variant: 'info', title: 'Усталость глаз и дистанция', icon: 'mdi:information', badge: 'Здоровье зрения', html: 'Слишком близкое расстояние утомляет, так как глазам приходится постоянно адаптироваться. Слишком далекое вынуждает напрягаться для различения деталей. Наш калькулятор находит «золотую середину» (40° для THX).' },
118
+ { type: 'diagnostic', variant: 'info', title: 'Усталость глаз и дистанция', icon: 'mdi:information', badge: 'Здоровье зрения', html: 'Слишком близкое расстояние утомляет, так как глазам приходится постоянно адаптироваться. Слишком далекое вынуждает напрягаться для различения деталей. Наш калькулятор находит \"золотую середину\" (40° для THX).' },
119
119
 
120
120
  { type: 'proscons', items: [
121
121
  {
@@ -123,7 +123,7 @@ const seo: TvDistanceLocaleContent['seo'] = [
123
123
  con: 'Требует больше свободного места в комнате'
124
124
  },
125
125
  {
126
- pro: '4K позволяет сидеть ближе, чем 1080p удобно в малых пространствах',
126
+ pro: '4K позволяет сидеть ближе, чем 1080p - удобно в малых пространствах',
127
127
  con: 'Нужно быть на минимальной дистанции, чтобы видеть все пиксели'
128
128
  },
129
129
  {
@@ -143,7 +143,7 @@ const seo: TvDistanceLocaleContent['seo'] = [
143
143
  },
144
144
  {
145
145
  term: 'THX',
146
- definition: 'Сертификация качества от Lucasfilm. Определяет стандарты для кинозалов и домашних театров. 40° их главная рекомендация.'
146
+ definition: 'Сертификация качества от Lucasfilm. Определяет стандарты для кинозалов и домашних театров. 40° - их главная рекомендация.'
147
147
  },
148
148
  {
149
149
  term: 'SMPTE',
@@ -52,7 +52,7 @@ const howTo: TvDistanceLocaleContent['howTo'] = [
52
52
  },
53
53
  {
54
54
  name: "调整沙发位置",
55
- text: "将您的座位放置在“最佳观看距离”范围内,以实现最大的电影沉浸感。",
55
+ text: "将您的座位放置在\"最佳观看距离\"范围内,以实现最大的电影沉浸感。",
56
56
  },
57
57
  ];
58
58
 
@@ -113,9 +113,9 @@ const seo: TvDistanceLocaleContent['seo'] = [
113
113
 
114
114
  { type: 'paragraph', html: '如您所见,更高分辨率允许您坐得更近而不会察觉到像素结构。4K 电视在 1.2 米处即可获得极佳体验,而 1080p 则需要至少 2 米。' },
115
115
 
116
- { type: 'card', title: '人类视觉敏锐度极限', html: '人眼的辨别能力(视觉敏锐度)是有极限的。超过一定距离,即使屏幕是 8K,您也无法区分更多细节。我们的计算让您准确处于“最佳区域”,在不浪费眼力的情况下 100% 发挥像素性能。' },
116
+ { type: 'card', title: '人类视觉敏锐度极限', html: '人眼的辨别能力(视觉敏锐度)是有极限的。超过一定距离,即使屏幕是 8K,您也无法区分更多细节。我们的计算让您准确处于\"最佳区域\",在不浪费眼力的情况下 100% 发挥像素性能。' },
117
117
 
118
- { type: 'diagnostic', variant: 'info', title: '视觉疲劳与距离', icon: 'mdi:information', badge: '视觉健康', html: '距离太近会导致疲劳,因为眼睛需要不断适应极端的角度。距离太远会导致为了看清细节而产生肌肉紧张。我们的计算器为您找到“黄金平衡点”(THX 标准下的 40°视角)。' },
118
+ { type: 'diagnostic', variant: 'info', title: '视觉疲劳与距离', icon: 'mdi:information', badge: '视觉健康', html: '距离太近会导致疲劳,因为眼睛需要不断适应极端的角度。距离太远会导致为了看清细节而产生肌肉紧张。我们的计算器为您找到\"黄金平衡点\"(THX 标准下的 40°视角)。' },
119
119
 
120
120
  { type: 'proscons', items: [
121
121
  {
@@ -162,7 +162,7 @@ const seo: TvDistanceLocaleContent['seo'] = [
162
162
  { type: 'message', title: '专业视听空间优化', ariaLabel: '关于电视设置标准的信息', html: '专业电影院花费巨资确保距离、角度和照明完美。我们的计算器将这些同样的原则带到您的家中。这不是奢侈品:这是对视觉舒适度的投资。' },
163
163
 
164
164
  { type: 'title', text: '打造专业级的家庭影院', level: 3 },
165
- { type: 'paragraph', html: '距离与屏幕尺寸和分辨率“同样重要”。遵循这些标准,将您的客厅转变成真正的私人影厅。' }
165
+ { type: 'paragraph', html: '距离与屏幕尺寸和分辨率\"同样重要\"。遵循这些标准,将您的客厅转变成真正的私人影厅。' }
166
166
  ];
167
167
 
168
168
  const faqSchema: WithContext<FAQPage> = {
@@ -67,7 +67,7 @@ const seo: VideoFrameExtractorLocaleContent['seo'] = [
67
67
  'Extraction par lots automatique à intervalles personnalisés'
68
68
  ]
69
69
  },
70
- { type: 'title', text: 'Extraction d\'Images : Figer le Temps en Vidéo', level: 2 },
70
+ { type: 'title', text: 'Extraction d\'Images: Figer le Temps en Vidéo', level: 2 },
71
71
  { type: 'paragraph', html: 'Une image vaut parfois mille mots. Mais trouver l\'image parfaite peut être frustrant. Notre outil utilise la puissance locale de votre navigateur pour extraire des images de précision sans logiciel professionnel.' },
72
72
 
73
73
  { type: 'stats', items: [
@@ -129,15 +129,15 @@ const seo: VideoFrameExtractorLocaleContent['seo'] = [
129
129
  ['Matroska', 'MKV', 'Navigateurs modernes', 'Conteneur flexible, qualité variable']
130
130
  ] },
131
131
 
132
- { type: 'card', title: 'Précision à l\'Image Près', html: 'Se déplacer d\'une seule image en avant ou en arrière (±1 image) est vital pour capturer l\'instant parfait : un saut, un sourire, un geste. Notre outil vous donne un contrôle millimétrique.' },
132
+ { type: 'card', title: 'Précision à l\'Image Près', html: 'Se déplacer d\'une seule image en avant ou en arrière (±1 image) est vital pour capturer l\'instant parfait: un saut, un sourire, un geste. Notre outil vous donne un contrôle millimétrique.' },
133
133
 
134
134
  { type: 'proscons', items: [
135
135
  {
136
- pro: 'Confidentialité totale : la vidéo est traitée à 100 % localement',
136
+ pro: 'Confidentialité totale: la vidéo est traitée à 100 % localement',
137
137
  con: 'Limité par la mémoire RAM disponible (~500 Mo recommandés)'
138
138
  },
139
139
  {
140
- pro: 'Résolution native préservée : SD, HD, 4K sans re-compression',
140
+ pro: 'Résolution native préservée: SD, HD, 4K sans re-compression',
141
141
  con: 'Nécessite un navigateur supportant HTML5 Video'
142
142
  },
143
143
  {
@@ -159,11 +159,11 @@ const seo: VideoFrameExtractorLocaleContent['seo'] = [
159
159
  },
160
160
  {
161
161
  term: 'FPS (Images par seconde)',
162
- definition: 'Vitesse de défilement : 24 fps (cinéma), 30 fps (vidéo web), 60 fps (fluide).'
162
+ definition: 'Vitesse de défilement: 24 fps (cinéma), 30 fps (vidéo web), 60 fps (fluide).'
163
163
  },
164
164
  {
165
165
  term: 'Codec Vidéo',
166
- definition: 'Algorithme de compression : H.264 (MP4), VP9 (WebM). Détermine la taille et la qualité.'
166
+ definition: 'Algorithme de compression: H.264 (MP4), VP9 (WebM). Détermine la taille et la qualité.'
167
167
  },
168
168
  {
169
169
  term: 'Bitrate',
@@ -171,11 +171,11 @@ const seo: VideoFrameExtractorLocaleContent['seo'] = [
171
171
  },
172
172
  {
173
173
  term: 'Résolution Vidéo',
174
- definition: 'Dimensions en pixels : 720p (1280x720), 1080p (1920x1080), 4K (3840x2160).'
174
+ definition: 'Dimensions en pixels: 720p (1280x720), 1080p (1920x1080), 4K (3840x2160).'
175
175
  }
176
176
  ] },
177
177
 
178
- { type: 'message', title: 'Extraction Professionnelle d\'Images', ariaLabel: 'Informations techniques', html: 'L\'image parfaite est à portée de clic : importez, naviguez, capturez. Confidentialité totale, résolution native, téléchargement instantané.' },
178
+ { type: 'message', title: 'Extraction Professionnelle d\'Images', ariaLabel: 'Informations techniques', html: 'L\'image parfaite est à portée de clic: importez, naviguez, capturez. Confidentialité totale, résolution native, téléchargement instantané.' },
179
179
 
180
180
  { type: 'title', text: 'Figer des Moments Vidéo', level: 3 },
181
181
  { type: 'paragraph', html: 'Chaque vidéo contient des centaines d\'images. Beaucoup sont des pépites. Utilisez cet outil pour extraire ces moments parfaits.' }
@@ -44,7 +44,7 @@ const howTo: VideoFrameExtractorLocaleContent['howTo'] = [
44
44
  },
45
45
  {
46
46
  name: "Перейдите к точному моменту",
47
- text: "Используйте шкалу времени или кнопки «±1 кадр» для идеальной точности.",
47
+ text: "Используйте шкалу времени или кнопки \"±1 кадр\" для идеальной точности.",
48
48
  },
49
49
  {
50
50
  name: "Захватите кадр",
@@ -167,7 +167,7 @@ const seo: VideoFrameExtractorLocaleContent['seo'] = [
167
167
  },
168
168
  {
169
169
  term: 'Битрейт',
170
- definition: 'Количество данных в секунду. Выше битрейт выше качество.'
170
+ definition: 'Количество данных в секунду. Выше битрейт - выше качество.'
171
171
  },
172
172
  {
173
173
  term: 'Разрешение',
@@ -0,0 +1,17 @@
1
+ ---
2
+ import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
+ import { videoMerger } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await videoMerger.i18n[locale]?.();
12
+ if (!content || !content.bibliography || content.bibliography.length === 0) return null;
13
+
14
+ const { bibliography } = content;
15
+ ---
16
+
17
+ <SharedBibliography links={bibliography} />
@@ -0,0 +1,16 @@
1
+ import type { BibliographyEntry } from '../../types';
2
+
3
+ export const bibliography: BibliographyEntry[] = [
4
+ {
5
+ name: "HTML Canvas CaptureStream API",
6
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/captureStream",
7
+ },
8
+ {
9
+ name: "Web Audio API and AudioContext",
10
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API",
11
+ },
12
+ {
13
+ name: "MediaRecorder API for Client-side Recording",
14
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder",
15
+ },
16
+ ];