OpenSource-проекты для работы с видео и торрентами.
На этой страничке я расскажу о некоторых своих соображениях по работе с видео. Ну во-первых, как их проигрывать - это я отработал уже года два назад и описал вначале этой странички. Тогда я поднимал тему комментирования видео-ролика на той же форме, что и проигрывание - без его перезагрузки с самого начала. Выводы, к которым я пришел два года назад - я подверждаю и сегодня. AJAX - по крайней мере для этой цели (а он именно для нее задекларирован) - абсолютно непригоден. Зато эта же задача замечательно решается при прокрутке ролика во фрейме.
На упомянутой страничке я рассматривал прокрутку исключительно FLV-ролика c помощью небольшого OpenSource-проекта SWFObject. Наверное от этой практики отходить не следует и сегодня (хотя MS и проталкивает проигрывание формата .WMV, есть проект Silverlight и прочие маловразумительные альтернативы). Но при работе с видео возникают еще ряд важнейших вопросов, которые мы и рассмотрим на этой странице.
- Как выполнить распознавание типа медиа-файла, который подсовывает нам пользователь
- Как изготовить превью-превью ролика (взять фрейм например из пятой секунды ролика и использовать его как изображение всего ролика)
- Как выполнить онлайн-конвертацию видео-файла произвольного формата к формату FLV
- Как вообще распространять видео-файлы
Все эти задачи сегодня решаются за рамками ASP.NET - програмирования. В знаменитых OpenSource-проектах MediaInfo, FFMPEG, MediaCoder, VUZE.
Это мои любимые OpenSource-проекты, неоднократно упомянутые на моем сайте, например на страничке - Эра цифрового TV. Я пользуюсь этими прогами и на сайтах и просто для работы в диалоговых режимах (для работы в диалогах указанные четыре проекта хорошо бы дополнить как минимум VLC, K-Lite Codec Pack, VirtualDub). Но на этой страничке мы сосредоточимся на программном использовании этих четырех замечательных OpenSource-проектов в собственных сайтах на ASP.NET.MediaInfo
Это важнейший проект, позволяющий определить какой именно файл подсовывает нам пользователь. Без распознавания типа видео-файла (и видео ли это вообще) никакие дальнейшие решения с загружаемым файлом невозможны. Поэтому все мои странички загрузки выводят примерно вот такой скрин. Ниже вы можете видеть начальный фрагмент кода (подвергавшийся потом множеству неприниципиальных для этого разговора доработок). В строках 335-340 вы можете видеть, как вызывается этот проект на страничках ASP.NET. Это слегка коряво, но иного пути нет.
Обратите внимание, что для каждого из этих проектов перед использованием EXE-файла - его неободимо разблокировать.
00325: Sub CheckVideo(ByVal SourceFileName As String)
00326: Dim TargetVideoFileName As String = IO.Path.ChangeExtension(SourceFileName, "flv")
00327: Dim SourceInfoFileName As String = IO.Path.ChangeExtension(SourceFileName, "txt")
00328: Dim PreviewFileName As String = IO.Path.ChangeExtension(SourceFileName, "jpg")
00329: Dim VideoInfo As String
00330: '
00331: Try
00332: 'эта прога бывает 32-х и 64-х разрядная. В моей девелоперской среде 64-разряда, в боевой - 32-х разрядная
00333: 'плюс требует разблокировки
00334: Dim MEDIAINFO As New System.Diagnostics.Process
00335: MEDIAINFO.StartInfo.Arguments = SourceFileName & " --LogFile=""" & SourceInfoFileName & """"
00336: MEDIAINFO.StartInfo.FileName = System.IO.Path.Combine(System.Configuration.ConfigurationManager.AppSettings("RootVideoPatch"), "MediaInfo.exe")
00337: MEDIAINFO.StartInfo.WorkingDirectory = System.Configuration.ConfigurationManager.AppSettings("RootVideoPatch")
00338: MEDIAINFO.Start()
00339: MEDIAINFO.WaitForExit()
00340: MEDIAINFO.Close()
00341: Catch ex As Exception
00342: LErr.Visible = True
00343: LErr.Text = "Не удалось понять формат загруженного файла: " & vbCrLf & ex.Message
00344: Exit Sub
00345: End Try
00346: '
00347: If My.Computer.FileSystem.FileExists(SourceInfoFileName) Then
00348: VideoInfo = My.Computer.FileSystem.ReadAllText(SourceInfoFileName)
00349: If VideoInfo.Contains("Video") And VideoInfo.Contains("Audio") And VideoInfo.Contains("Format") Then
00350: LInfo.Text = VideoInfo.Replace(vbCrLf, "<br>")
00351: Else
00352: LErr.Visible = True
00353: LErr.Text = "Не удалось понять формат загруженного файла. "
00354: Exit Sub
00355: End If
00356: Else
00357: LErr.Visible = True
00358: LErr.Text = "Не удалось понять формат загруженного файла. "
00359: Exit Sub
00360: End If
00361: '
00362: 'загружен видео-файл
00363: Try
00364: Dim FFMPEG As New System.Diagnostics.Process
00365: FFMPEG.StartInfo.Arguments = "-i " & SourceFileName & " -f image2 -vframes 1 -ss 5 " & PreviewFileName
00366: FFMPEG.StartInfo.FileName = System.IO.Path.Combine(System.Configuration.ConfigurationManager.AppSettings("RootVideoPatch"), "FFMPEG.exe")
00367: FFMPEG.Start()
00368: FFMPEG.WaitForExit()
00369: FFMPEG.Close()
00370: '
00371: LImage1.Text = "Создано превью вашего видеоролика."
00372: Image1.ImageUrl = "http://video.dev.vm/GetPreView.ashx?j=" & Request.QueryString("j")
00373: Catch ex As Exception
00374: LErr.Visible = True
00375: LErr.Text = "Не удалось создать превью ролика: " & vbCrLf & ex.Message
00376: Image1.Visible = False
00377: Exit Sub
00378: End Try
00379: '
00380: 'превьюшному хандлеру нужен формат
00381: '279df484-7c3c-40fa-8d02-914c03aa7e75\d488f713-1eef-4192-9895-7cc026135551.jpg
00382: Dim StartPos1 As Integer = PreviewFileName.IndexOf("FLV\")
00383: SavePreviewName.SelectParameters("PreView").DefaultValue = PreviewFileName.Substring(StartPos1 + 4)
00384: SavePreviewName.Select(New DataSourceSelectArguments)
00385: '
00386: If VideoInfo.Contains("Format : Flash Video") Then 'еще надо проверять длину ролика и разрешение
00387: 'ставим ConvertStatus=0 - в конвертации не нуждается
00388: Try
00389: 'форме воспроизведения нужен формат
00390: 'FLV/279df484-7c3c-40fa-8d02-914c03aa7e75\d488f713-1eef-4192-9895-7cc026135551.flv
00391: SaveVideoName.SelectParameters("ToFile").DefaultValue = TargetVideoFileName.Substring(StartPos1)
00392: SaveVideoName.Select(New DataSourceSelectArguments)
00393: Lmess.Text = "Обработка видеоролика завершена"
00394: Exit Sub
00395: Catch ex As Exception
00396: LErr.Visible = True
00397: LErr.Text = "Ошибка файловой операции: " & vbCrLf & ex.Message
00398: Exit Sub
00399: End Try
00400: Else
00401: Lmess.Text = "Видеоролик нуждается в конвертации. Конвертация начата. После конвертации он будет доступен для просмотра. Проверьте ваш ролик через 10-20 минут."
00402: End If
00403: End Sub
FFMPEG
Этот знаменитый OpenSource-проект FFMPEG стандартно входит в PHP в виде обьектно-ориентированной библиотеки - phpvideotoolkit. В ASP.NET этот проект можно использовать только так же коряво как и предыдущий проект, но ведь мы не в PHP - и красивой обьктно-ориентированной технологии к этому OpenSource продукту в аспе нет.
Вообще FFMPEG многое делает (например звук им перекодируют часто), но в строках (строки 364-369) вы можете увидеть, как я получил с его помощью Preview видео-ролика. У проекта FFMPEG существует обширная документация и горы параметров, которые позволяют например делать превьюшку не по пятой секунде ролика, а по десятой или получить FLV из какого-то иного формата.
Порт FFMPEG для Windows выкладывается здесь. В моей клинической практике мне попадались такие типы, которые не только не знают о существовании FFMPEG, но даже на этой страничке со ссылками не смогли разобраться куда тыкнуть, чтобы сгрузить FFMPEG - для таких я выкладываю некий устаревший клон прямо у себя - download ffmpeg for windows.
Для представления ролика в ASP.NET сайте должен существовать контрол, который формирует пару ссылок - непосредственно на форму просмотра и на загрузку превьюшки. Например в моем проекте эти ссылки на контрое выглядят вот так:
LinkTitle.NavigateUrl = "~/video_play.aspx?i=" & ViewState("i") & "&j=" & ViewState("j")
Image1.ImageUrl = "GetPreView.ashx?j=" & ViewState("j")
Далее существует форма непосредственно плеера (которую я описывать не буду) и хандлер для показа превьюшки, который выглядит примерно так:
00001: <%@ WebHandler Language="VB" Class="GetPreView" %>
00002:
00003: Imports System
00004: Imports System.Web
00005:
00006: Public Class GetPreView : Implements IHttpHandler
00007:
00008: Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
00009: context.Response.ContentType = "image/bmp"
00010: Dim J As Integer 'собственно номер рисунка по базе
00011: Dim W As Integer 'заданная ширина вывода рисунка или 0 (вывод без мастабирования)
00012: Try
00013: If context.Current.Request.QueryString("J") <> Nothing Then
00014:
00015: 'выудим расшифрованный номер отображаемого рисунка в UserData
00016: J = VBNET2000.PP8_Helper.Unmask_QueryString("J", "SQLServer_ConnectionStrings")
00017: If context.Current.Request.QueryString("W") IsNot Nothing Then W = CInt(context.Current.Request.QueryString("W")) Else W = 0
00018: '
00019: Dim CN As New System.Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("SQLServer_ConnectionStrings").ConnectionString)
00020: CN.Open() 'здесь иногда валится по таймауту или из-за исчерпания пула подключений (задаются Max Pool Size в коннекшн-стринге)
00021: Dim PreviewInfo As New System.Data.SqlClient.SqlCommand("select * from dbo.UserVideo with (Nolock) where I=@I", CN)
00022: PreviewInfo.Parameters.AddWithValue("I", J)
00023: Dim RDR As Data.SqlClient.SqlDataReader = PreviewInfo.ExecuteReader()
00024: If RDR.Read Then
00025: If IsDBNull(RDR("IsModerBan")) Then
00026: If Not IsDBNull(RDR("Preview")) Then
00027: Dim PreviewShortFileName As String = RDR("Preview")
00028: If PreviewShortFileName <> "" And PreviewShortFileName <> " " Then
00029: Dim PreviewFullFileName As String = System.IO.Path.Combine(context.Current.Server.MapPath("FLV"), PreviewShortFileName)
00030: context.Current.Response.BinaryWrite(My.Computer.FileSystem.ReadAllBytes(PreviewFullFileName))
00031: Exit Sub
00032: Else
00033: WriteLogo(context) 'ерунда вместо имени файла
00034: End If
00035: Else
00036: WriteLogo(context) 'не отработала FFMPEG
00037: End If
00038: Else
00039: WriteBanLogo(context)
00040: End If
00041: else
00042: WriteLogo(context) 'нету такой записи
00043: End If
00044:
00045: Else
00046: WriteLogo(context) 'не указан номер рисунка
00047: End If
00048: Catch ex As Exception
00049: WriteLogo(context)
00050: My.Log.WriteEntry("Ошибка вывода превью " & J.ToString & " запросом " & context.Current.Request.RawUrl)
00051: End Try
00052: End Sub
00053:
00054: Private Sub WriteLogo(ByVal context As HttpContext)
00055: context.Response.BinaryWrite(Image1.StripSize(My.Computer.FileSystem.ReadAllBytes(context.Server.MapPath("Images/logo_n.gif")), 164))
00056: End Sub
00057:
00058: Private Sub WriteBanLogo(ByVal context As HttpContext)
00059: context.Response.BinaryWrite(Image1.StripSize(My.Computer.FileSystem.ReadAllBytes(context.Server.MapPath("Images/ban.gif")), 164))
00060: End Sub
00061:
00062: Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
00063: Get
00064: Return False
00065: End Get
00066: End Property
00067:
00068: End Class
Использование OpenSource-проекта FFMPEG здесь показано в самом убогом варианте - с хранением видео в файловой системе. Более изощренное решение будет использовать хранение роликов в SQL-сервере и секционирование хранимого видео по множеству физических дисков средствами SQL-сервера.
К сожалению на практике собственно перекодировка в FLV c помощью ffmpag обычно завершается с проблемами, поэтому для перекодировок приходится исользовать более надежные технологии, например MediaCoder.
MediaCoder
Это еще один важнейший OpenSource-проект для работы с видео. Он имеет некоторые ограничения. В частности, в диалогах он не умеет сливать отдельные фрагменты AVI-файлов, поэтому он дополняется проектом VirtualDub, который как раз и предназначен для слияния отдельных фрагментов AVI-файлов в один общий файл. Но сами по себе передикодировки отдельных AVI-файлов MediaCoder выполняет идеально.
Идеально, за исключением главного. Компонент доступа к ядру перекодировок платный. Те в диалогах, как пользователь вы можете пользоваться этим проектом бесплатно и без ограничений, но если вы пишите СВОЮ системы на базе этого ядра, то командная строка для доступа к ядру стоит $299. Что конечно же, совсем немного - учитывая качество проекта. Кроме того, даже этот платный компонент умеет перекодировать 3 минуты видео без оплаты.
В теме перекодировки видео существует та проблема, что МОЩНАЯ РАСЧЕТНАЯ ЗАДАЧА. И исходя из этого надо строить всю идею использования этого проекта.
Я считаю невозможным использования для перекодирования видео каких-либо асинхронных страничек, по типу этого моего решения - в силу снижения реактивности работы сайта и общего торможения IIS при наличии у него в дочерних процессах мощнейшей и долгоиграющей расчетной задачи. Кроме того, перекодирование иногда просто тупо виснет и лечится только полным просто перезапуском IIS.
Поэтому единственное решение видимое мне решение - это отдельно выполненный сервер видеоконвертации. Идеально он должен быть вынесен вообще на отдельный физический кампутер (отдельно от SQL-сервера и от WEB-сервера). В качестве промежуточного решения возможна виртуалка на WEB-сервере с ограничением на использование процессорного времени - скажем в 10%. Это не будет снижать реактивность IIS, но в 10 раз увеличит ВРЕМЯ ОЖИДАНИЯ пользователем перекордирования.
Итак, я обьяснил - почему я считаю возможным использование этого проекта ИСКЛЮЧИТЕЛЬНО в виде отдельного сервера видеоконвертации. Именно такое WIN-приложение я и опишу ниже.
Я очень люблю всякие подобного рода сервисы, которые просто сидят в трее и щелкнув на иконке в трее - можно увидеть, что именно сейчас этот сервер конвертирует. У меня на сайте много таких приложений опубликовано. Самое близкое по логике работы приложение подобного рода - многопоточный прокси-сервер скрины работы которого выглядят так. Сходство здесь не только во внешнем интерфейсе сервера, но и в многопоточности работы.
Конечно можно сказать, что для расчетной задачи многопоточность бессмысленна, но обратите внимание как я ее решил. Одномоментно запускается только один певдопоток (даже при наличи нескольких запросов на конвертацию). Дальше запускающий конвертации процесс переходит в ожидание на указанное время. И по его прошествии опять проверяет запросы на конвертацию и (при их наличии) запускает новые потоки конвертации. Надо четко понимать, что конвертация может навсегда зависнуть (а может быть даже и закончится ДО запуска новой конвертации) - поэтому я и решил этот сервер в многопоточном варианте.
Как видите, я не стал тут заморачиваться через COM+ или его .NET-обертки, а запросы и ответы от WEB-приложения к серверу видеоконвертации реализовал через базу. Львиная доля кода тут манипулирует путями по сайту. Это совершенно неважный функционал в общем случае, ибо я написал видеоконвертер для работающего сайта. В котором уже горы кода используют те или иные соглашения по путям к видеофайлам. Разумееется и структура данных в вашем случае будет иная - поэтому этот специфический функционал я не показываю и не обсуждаю. Структура базы и пути периодически меняется даже в моем проекте - поэтому я даже строки запросов к базе вынес в параметры, чтобы легко менять их на ходу без перекомпиляции сервера.
Я использовал в этом проекте BackgroundWorker, заданный декларативно. После старта форма сокращается в трей и в бекграунде к потоку формы стартует поток опроса базы в поисках запросов на конвертацию:
00032: Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
00033: Me.WindowState = FormWindowState.Minimized
00034: ReConnect()
00035: BackgroundWorker1.RunWorkerAsync(2000)
00036: Me.Visible = False
00037: End Sub
Процесс опроса базы запускает дочерние .NET-псевдопроцессы. Переодически опрашивая базу через время SurveyTime. Каждый отдельный процесс конвертации запускается в отдельном псевдопроцессе. И за один опрос - запускается одна конвертация. Это как раз и сделано из-за того, что это чисто расчетная задачка и запуск одновременной конвертации всех ожидающих видеофайлов лишь усилит конкуренцию и снизит скорость конвертации.
00063: Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
00064: Survey()
00065: End Sub
00066:
00067: Sub Survey()
00068: While Survey_CMD.Connection.State = ConnectionState.Open
00069: 'все что нужно конвертировать - запускаем отдельными потоками
00070: Dim Survey_RDR = Survey_CMD.ExecuteReader
00071: If Survey_RDR.Read Then
00072: Dim OneConvertingThread As New Threading.Thread(AddressOf OneConverting.GoCoder)
00073: OneConvertingThread.Priority = Threading.ThreadPriority.Lowest
00074: OneConvertingThread.Name = "Convert UserVideo Record # " & Survey_RDR("i")
00075: 'фиксируем начало процесса конвертации
00076: Start_CMD.Parameters("i").Value = Survey_RDR("i")
00077: Start_CMD.ExecuteNonQuery()
00078: 'запускаем процесс конвертации
00079: OneConvertingThread.Start(Survey_RDR("i"))
00080: End If
00081: Survey_RDR.Close()
00082: 'ждем
00083: Threading.Thread.Sleep(My.Settings.SurveyTime)
00084: End While
00085: End Sub
00086:
Сам по себе класс конвертации выглядит вот так, в котором в строках 157-163 вы можете видеть вызов того самого обсуждаемого в этом разделе проекта MediaCoder.
00136: Class OneConverting
00137: Shared Sub GoCoder(ByVal i As Integer)
00138: Dim Convert_CN = New System.Data.SqlClient.SqlConnection(My.Settings.SQLServer_ConnectionStrings)
00139: Convert_CN.Open()
00140: 'получаем имя файла конвертации из базы
00141: Dim SelectOne_CMD As New System.Data.SqlClient.SqlCommand(My.Settings.SelectOne_Query, Convert_CN)
00142: SelectOne_CMD.Parameters.AddWithValue("i", i)
00143: Dim SelectOne_RDR = SelectOne_CMD.ExecuteReader
00144: If SelectOne_RDR.Read Then
00145: Dim SourceFileName As String = SelectOne_RDR("SourceFile")
00146: SelectOne_RDR.Close()
00147: 'получаем расшаренное имя для этого файла
00148: 'для локальной отладки SUBST Q: G:\WWW\All_votpusk\Video\FLV
00149: Dim StartPos1 As Integer = SourceFileName.IndexOf("FLV\")
00150: Dim SharedSourceFileName As String = (My.Settings.FLVFolder_ShareDiskName & SourceFileName.Substring(StartPos1 + 3)).Replace("/", "\")
00151: Dim SharedTargetFileName As String = IO.Path.ChangeExtension(SharedSourceFileName, "flv")
00152: Dim RestrictFileName As String = IO.Path.ChangeExtension(SourceFileName.Substring(StartPos1), "flv")
00153: If My.Computer.FileSystem.FileExists(SharedTargetFileName) Then My.Computer.FileSystem.DeleteFile(SharedTargetFileName)
00154: '
00155: Try
00156: 'запускаем собственно конвертацию
00157: Dim MediaCoder As New System.Diagnostics.Process
00158: MediaCoder.StartInfo.Arguments = My.Settings.Converting_Options & " -o " & SharedTargetFileName & " " & SharedSourceFileName
00159: MediaCoder.StartInfo.FileName = System.IO.Path.Combine(My.Settings.MediaCoder_Directory, "mc.exe")
00160: MediaCoder.Start()
00161: MediaCoder.WaitForExit()
00162: MediaCoder.Close()
00163: '
00164: 'фиксируем завершение процесса конвертации
00165: Dim End_CMD As New System.Data.SqlClient.SqlCommand(My.Settings.ConvertingEnd_CMD, Convert_CN)
00166: End_CMD.Parameters.AddWithValue("i", i)
00167: If My.Computer.FileSystem.FileExists(SharedTargetFileName) Then
00168: End_CMD.Parameters.AddWithValue("Status", 0)
00169: End_CMD.Parameters.AddWithValue("TargetFileName", RestrictFileName)
00170: Else
00171: End_CMD.Parameters.AddWithValue("Status", 1)
00172: End_CMD.Parameters.AddWithValue("TargetFileName", "")
00173: End If
00174: End_CMD.ExecuteNonQuery()
00175: Catch ex As Exception
00176: 'Ничего не делаем - на конвертации этого файла MediaCoder упал
00177: End Try
00178: '
00179: End If
00180: Convert_CN.Close()
00181: End Sub
Еще в этом сервере видеоконвертации существует основной процесс формы (от которого запускался BackgroundWorker с опросом базы). В этом процессе выполняется ручной рефреш формы. Чтобы выполнить такой рефреш автоматически (при появлении запроса на конвертацию) необходимо сделать маршалинг Background-потока (с помощью Invoke) в основной поток формы. Но в данном случае включать этот функционал именно в сервер конвертации я посчитал бессмысленным, ибо в админке сайта есть аналогичный функционал с Web-интерфейсом.
00047: Private Sub Refresh_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Refresh.Click
00048: If Browse_CMD.Connection.State = ConnectionState.Open Then
00049: 'отображение
00050: Dim Browse_RDR = Browse_CMD.ExecuteReader
00051: Dim DT As New Data.DataTable
00052: DT.Load(Browse_RDR)
00053: Browse_RDR.Close()
00054: If DT.Rows.Count > 0 Then
00055: DataGridView1.DataSource = DT
00056: Else
00057: DataGridView1.DataSource = Nothing
00058: End If
00059: DataGridView1.Refresh()
00060: End If
00061: End Sub
Как видите, при проектировании сервера видеоконвертации я основное внимание уделил тем нередким ситуациям, когда видео-конвертация невыполнима. При этом безвозвратно умирает всего один поток, а сервер продолжает и продолжает опрашивать базу на предмет новых и новых запросов на конвертацию и запускать все новые и новые конвертации. Безусловно, через какое-то время память виртуалки исчерпается зависшими процессами конвертации и сервис придется перезапустить. Но эта многопоточная схема позволяет сохранить независимость обработки конвертации видеороликов одного юзера от другого и устойчивость самого сервиса конвертации в течении достаточно длительного времени.
VUZE
Еще одна тема работы с видео - это работа с торрентами. Вообще сайтам работать с видео в любой форме крайне вредно с точки зрения модерации. Непонятно сколько человек должно все это просматривать даже для сайта со ста загруженными роликами в день. А для сайтов с торрентами модерация невозможна в принципе - ибо это высшая технология работы с видео. При модерации торрентов может так случиться, что модератор сайта так и не скачает себе для модерации ролик, а сто человек уже скачает. А там, например, педофилический ролик, в котором наш фюрер демонстрирует публично свои модные педофилические наклонности - задирает ребенку маечку, находит там детский пупочек и засасывает этого ребенка в пупочек - даже не стесняясь оторопевшей публики.
Поэтому сайтам с жесткой модерацией контента вообще не следует заморачиваться на динамически загружаемых торрентах. Хотя это крайне выгодный на мой взгляд вид распространения заведомо просмотренных и заведомо загруженных модератором видео. И это лучший способ экономии ресурсов на серверах для динамически загружаемого видео. Ведь сам торрент - представляет собой ссылку (наподобие URL, только снабженную еще хэш-кодом ролика, который лежит по этой ссылке) и совершенно не отнимает ресурсов сайта. В отличии от собственно видео, где загрузки даже по сто человек в день полностью способны разорить любую фирму покупками новых и новых серверов.
Но, все-таки, как же работать с динамически загружаемыми торрентами в сайтах без жесткой модерации контента? А очень просто. Во-первых, надо взять какой-нибудь знаменитый OpenSource проект - лично я предпочитаю для этих целей именно VUZE. Одна из причин моего выбора - у Вуза есть мошный форум поддержки, на котором сидят постоянно сотни (иногда тысячи) человек и отвечают на все вопросы по Вузу.
Так вот, основная фишка работы с VUZE в том, что он имеет почти сотню плагинов, причем множество из них либо вообще специально предназначено для Remote Access, либо имееет элементы Remote Access. Одним из таких ненавистных мною компонентов, (как бы даже и не предназначенных для Remote Access) является Universal Plug and Play - который используется Вузом для открывания портов фаерволов, закрытых вручную администратором.
Поэтому ставить VUZE на тот же Web-узел, что и сайт - нельзя с точки зрения безопасности. Кроме того, это проблематично и технически - Ява на 80-м порту будет конфликтовать с Аспом. Единственный реальный вариант - ставить VUZE на отдельную виртуалку. Это во-вторых.
А в-третьих, здесь возникает задачка, решение которой я не буду показывать реальным кодом - а просто опишу словами. После динамической загрузки торрента необходимо криптографически зашифрованный номер записи в базе (в которой уложен торрент) - передать реквестом на узел с виртуальной машиной с VUZE. В той машине (на некоем порту, не совпадающем с портом втроенного трекера VUZE) - живет сайт, который расшифрует переданный номер, достанет из базы торрент и вызовет в коммандной строке Azureus.exe имя_торрент_файла. Собственно вызов делается ровно так же, как это было сделано в коде выше. И торрент добавится к перечню закачек VUZE, который хостится возможно на другом хостинге (и с другими условиями оплаты трафика) - чем основной сайт на ASP.NET, куда производился Upload торрента.
Ну а превьюшку торрента, как вы понимаете, уже никак невозможно изготовить автоматически, ее можно только загрузить изначально. И вообще, пока торрент не докачан до конца - никак нельзя предсказать что содержится по ссылке торрента.
|