(ASP.NET) ASP.NET (2009 год)

OpenSource-проекты для работы с видео и торрентами.


На этой страничке я расскажу о некоторых своих соображениях по работе с видео. Ну во-первых, как их проигрывать - это я отработал уже года два назад и описал вначале этой странички. Тогда я поднимал тему комментирования видео-ролика на той же форме, что и проигрывание - без его перезагрузки с самого начала. Выводы, к которым я пришел два года назад - я подверждаю и сегодня. AJAX - по крайней мере для этой цели (а он именно для нее задекларирован) - абсолютно непригоден. Зато эта же задача замечательно решается при прокрутке ролика во фрейме.

На упомянутой страничке я рассматривал прокрутку исключительно FLV-ролика c помощью небольшого OpenSource-проекта SWFObject. Наверное от этой практики отходить не следует и сегодня (хотя MS и проталкивает проигрывание формата .WMV, есть проект Silverlight и прочие маловразумительные альтернативы). Но при работе с видео возникают еще ряд важнейших вопросов, которые мы и рассмотрим на этой странице.

Все эти задачи сегодня решаются за рамками 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 торрента.

Ну а превьюшку торрента, как вы понимаете, уже никак невозможно изготовить автоматически, ее можно только загрузить изначально. И вообще, пока торрент не докачан до конца - никак нельзя предсказать что содержится по ссылке торрента.



Comments ( )
Link to this page: //www.vb-net.com/asp2/43/index.htm
< THANKS ME>